/******************************************************************************/
/***************************** DECLARE VARIABLES ******************************/
/******************************************************************************/

var chartSize = 0, 
    windowWidth = 0, 
    windowHeight = 0, 
    headerHeight = 100, 
    leftWidth = 200, 
    rightWidth = 200, 
    planets = "1,2,4,5,6,7,8,9,10,11,12,19", 
    aspects = "48,49,50,51,52,56,69,70,71,72,73", 
    max = 15, 
    hasInnerText = false, 
    currentDateTimerActive = false, 
    currentDateTimerID = 0, 
    incrementChartTimerActive = false, 
    incrementChartTimerID = 0, 
    userDateTimeOutActive = false, 
    userDateTimeOutID = 0, 
    incAmount = 0, 
    incInterval = "",
    relativeDates = 1;

/* 0=date, 1=day_of_week, 2=month+day+year */
var dateRegExp  = /(\w+[, ]{1,2})?(\w+[, ]{1,2}\d{1,2}[, ]{1,2}\d{4})/;
var dateRegExp2 = /(\w+[, ]{1,2})?(\d{1,2} \w+ \d{4})/;

/* 0=time, 1=hr+mn+sc+am/pm, 2=tzString */
var timeRegExp = /(\d{1,2}:\d\d:?\d{0,2}[ AaMmPp]{0,3})[, ]{1,2}(.+)/;

//array, 0 is now, 1 is working chart, 2 is transit list
var dateInfo = new Array();
dateInfo['charts'] = new Array();

/******************************************************************************/
/***************************** DATE MANIPULATION ******************************/
/******************************************************************************/

/* takes a dateObject, extracts info from it, and returns an array, or false on error
    dateInfo['charts'][0]['dateObject']
    dateInfo['charts'][0]['localString']
    dateInfo['charts'][0]['shortString']
    dateInfo['charts'][0]['UTCFullString']
    dateInfo['charts'][0]['UTCStringURL']
    dateInfo['charts'][0]['tzOffset']
    dateInfo['charts'][0]['tzString']
    dateInfo['charts'][0]['timestampMs']
    dateInfo['charts'][0]['timestamp'] 
    dateInfo['charts'][0]['year'] 
    dateInfo['charts'][0]['month'] 
    dateInfo['charts'][0]['day'] */
function extractDateObject(dateObject) {
  if (typeof(dateObject) != "object") return false;
  else {
    var temp = new Array();
    
    //Set timestamps and dateObject to array, and get UTC string and tzOffset from dateObject
    temp['dateObject'] = dateObject;
    temp['UTCFullString'] = dateObject.toUTCString();
    temp['UTCStringURL'] = dateObject.getUTCFullYear()+"-"+(dateObject.getUTCMonth()+1)+"-"+dateObject.getUTCDate()+"%20"+dateObject.getUTCHours()+":"+dateObject.getUTCMinutes()+":"+dateObject.getUTCSeconds()+"%20UTC";
    temp['tzOffset'] = dateObject.getTimezoneOffset();
    temp['timestampMs'] = dateObject.getTime();
    temp['timestamp'] = Math.round(temp['timestampMs']/1000);
    temp['localYear'] = dateObject.getFullYear();
    temp['localMonth'] = dateObject.getMonth()+1;
    temp['localDay'] = dateObject.getDate();
    
    //Parse the local date/time string to get the tzString and a simplified date string
    var dateParts, timeParts = timeRegExp.exec(dateObject.toTimeString());
    if (!(dateParts = dateRegExp.exec(dateObject.toDateString()))) dateParts = dateRegExp2.exec(dateObject.toDateString())
    if (!dateParts || !timeParts) return false;
    temp['localString'] = dateParts[2];
    temp['shortString'] = dateParts[2].replace(/ *\d{4} */,'');
    temp['tzString'] = timeParts[2];
    var timeHour = dateObject.getHours(), timeMinutes = dateObject.getMinutes(), timeModifier;
    if (timeHour >= 12) {
      timeModifier = "PM";
      if (timeHour > 12) timeHour = timeHour-12;
    }
    else {
      timeModifier = "AM";
      if (timeHour == 0) timeHour = 12;
    }
    temp['localString'] = temp['localString'] + " " + timeHour + ":" + 
      (timeMinutes < 10 ? "0"+timeMinutes : timeMinutes) + " " + timeModifier;

    return temp;
  }
}

/* takes a timestamp, extracts info from it, and returns an array, or false on error */
function extractTimestamp(timestamp) {
  var workingTimestampMs = timestamp*1000;
  if (isNaN(workingTimestampMs)) return false;
  else {
    var dateObject = new Date();
    dateObject.setTime(workingTimestampMs);
    var temp = extractDateObject(dateObject);
    return temp;
  }
}

/* parses a dateString, extracts info from it, and returns an array, or false on error */
function parseDateString(dateString) {
  var workingTimestampMs = Date.parse(dateString);
  if (isNaN(workingTimestampMs)) return false;
  else {
    var temp = extractTimestamp(workingTimestampMs/1000);
    return temp;
  }
}

/* convert to julian day from timestamp or month, day, year, hour, minute, second */
function toJulianDay(MM,DD,YY,HR,MN,SC) {
	//If a timestamp is provided, calculate julian day from timestamp
  //if (!isNaN(MM) && isNaN(DD)) return (MM/86400 + 2440587.5);
  //Default to current date if none specified or non-numerical parameters
	if (isNaN(MM) || isNaN(DD) || isNaN(YY) || isNaN(HH) || isNaN(MN) || isNaN(SC)) {
    var now = new Date();
    MM = now.getUTCMonth() + 1;
  	DD = now.getUTCDate();
  	YY = now.getUTCFullYear();
  	HH = now.getUTCHours();
  	MN = now.getUTCMinutes();
  	SC = now.getUTCSeconds()
  }
  //Calculate the julian day
  HR = HR + (MN / 60) + (SC/3600);
  var GGG = 1;
  if (YY <= 1585) GGG = 0;
  var JD = -1 * Math.floor(7 * (Math.floor((MM + 9) / 12) + YY) / 4);
  var S = 1;
  if ((MM - 9)<0) S=-1;
  var A = Math.abs(MM - 9);
  var J1 = Math.floor(YY + S * Math.floor(A / 7));
  J1 = -1 * Math.floor((Math.floor(J1 / 100) + 1) * 3 / 4);
  var JD = JD + Math.floor(275 * MM / 9) + DD + (GGG * J1);
  JD = JD + 1721027 + 2 * GGG + 367 * YY - 0.5;
  JD = JD + (HR / 24);
  return JD;
}

/* convert from julian day. return array with month, day, year, hour, minute, second */
function fromJulianDay(julianDay) {
  var X = parseFloat(julianDay)+0.5;
  var Z = Math.floor(X);
  var F = X - Z;
  var Y = Math.floor((Z-1867216.25)/36524.25);
  var A = Z+1+Y-Math.floor(Y/4);
  var B = A+1524;
  var C = Math.floor((B-122.1)/365.25);
  var D = Math.floor(365.25*C);
  var G = Math.floor((B-D)/30.6001);
  var month = (G<13.5) ? (G-1) : (G-13);
  var year = (month<2.5) ? (C-4715) : (C-4716);
  var UT = B-D-Math.floor(30.6001*G)+F;
  var day = Math.floor(UT);
  UT -= Math.floor(UT);
  UT *= 24;
  var hour = Math.floor(UT);
  UT -= Math.floor(UT);
  UT *= 60;
  var minute = Math.floor(UT);
  UT -= Math.floor(UT);
  UT *= 60;
  var second = Math.round(UT);
  var gregDate;
  gregDate['month'] = month;
  gregDate['day'] = day;
  gregDate['year'] = year;
  gregDate['hour'] = hour;
  gregDate['minute'] = minute;
  gregDate['second'] = second;
  if (year < 10) year = "000"+year;
  else if (year < 100) year = "00"+year;
  else if (year < 1000) year = "0"+year;
  if (month < 10) month = "0"+month;
  if (day < 10) day = "0"+day;
  if (hour < 10) hour = "0"+hour;
  if (minute < 10) minute = "0"+minute;
  if (second < 10) second = "0"+second;
  gregDate['date'] = year+month+day+hour+minute+second;
  return gregDate;
}

/******************************************************************************/
/************************** PRIMARY CHART FUNCTIONS ***************************/
/******************************************************************************/

//Update the chart with whatever date is currently in the dateInfo['charts'][1] array
function updateChart(extraURLString) {
  userDateTimeOutActive = false;
  document.getElementById("chartWheel").src = "chartwheel.php?size="+chartSize+
            "&date="+encodeURIComponent(dateInfo['charts'][1]['UTCFullString'])+
            "&tzo="+dateInfo['charts'][1]['tzOffset']+
            "&tzs="+encodeURIComponent(dateInfo['charts'][1]['tzString'])+extraURLString;
  updateCalendar();
  return false;
}

//Fetch the transits and display them in either "update" format (relative to chart, offset by 1 week) or "next" format (with timestamp)
function getTransits(method, reverse) {
  if (typeof reverse == "undefined") reverse = "0";
  if (typeof(method)=="number") dateInfo['charts'][2] = extractTimestamp(method);
  else {
    if (!isNaN(parseInt(method))) dateInfo['charts'][2] = extractTimestamp(parseInt(method));
    else if (method == "update") dateInfo['charts'][2] = extractTimestamp(dateInfo['charts'][1]['timestamp'] + (-7*(60*60*24)));
  }
  var url = "gettransits.php?date="+dateInfo['charts'][2]['UTCFullString']+"&max="+max+"&planets="+planets+"&aspects="+aspects+"&tzo="+dateInfo['charts'][2]['tzOffset']+"&rel="+relativeDates+"&rev="+reverse;
  new Ajax.Updater('left', url, { method: 'get' });
  return false;
}

//Takes a timestamp and uses it to update the current chart, doesn't affect list of transits
function setChartToTimestamp(timestamp,extraURLString) {
  dateInfo['charts'][1] = extractTimestamp(timestamp);
  document.getElementById("userdate").value = dateInfo['charts'][1]['localString'];
  updateChart(extraURLString);
  return false;
}

//Set the dates of the charts to now and update the chart as well as the upcoming transits
function showCurrentChart() {
  dateInfo['charts'][0] = extractDateObject(new Date());
  dateInfo['charts'][1] = extractDateObject(dateInfo['charts'][0]['dateObject']);
  document.getElementById("userdate").value = dateInfo['charts'][1]['localString'];
  updateChart();
  getTransits("update");
  return false;
}

//Build a month calendar
function buildCalendar() {
  g_calendarObject = new JsDatePick({
    useMode:1,
    isStripped:true,
    target:"monthCalendar",
    selectedDate:{
      year:dateInfo['charts'][1]['localYear'],
      month:dateInfo['charts'][1]['localMonth'],
      day:dateInfo['charts'][1]['localDay']
    },
    yearsRange: new Array(1970,2037),
    cellColorScheme: "silver"
  });
  
  g_calendarObject.setOnSelectedDelegate(function(){
    var obj = g_calendarObject.getSelectedDay();

    //alert("a date was just selected and the date is : " + obj.day + "/" + obj.month + "/" + obj.year);
    dateInfo['charts'][1] = parseDateString(obj.month + "/" + obj.day + "/" + obj.year + " 12:00:00");
    document.getElementById("userdate").value = dateInfo['charts'][1]['localString'];
    updateChart();
  });
}

//Update the month calendar with the current chart (dateInfo['charts'][1])
function updateCalendar() {
  g_calendarObject.setSelectedDay({
    year:dateInfo['charts'][1]['localYear'],
    month:dateInfo['charts'][1]['localMonth'],
    day:dateInfo['charts'][1]['localDay']
  });
}

//Reveals the customizeTransitList container and initializes the form elements
function showCustomizeTransitList() {
  var planetsArray = planets.split(","), aspectsArray = aspects.split(",");
  
  $("transitList").style.display = "none";
  $("customizeTransitsForm").style.display = "block";
  
  $("toggleSunCheckbox").checked = in_array("2",planetsArray);
  $("toggleMercuryCheckbox").checked = in_array("4",planetsArray);
  $("toggleVenusCheckbox").checked = in_array("5",planetsArray);
  $("toggleMarsCheckbox").checked = in_array("6",planetsArray);
  $("toggleJupiterCheckbox").checked = in_array("7",planetsArray);
  $("toggleSaturnCheckbox").checked = in_array("8",planetsArray);
  $("toggleUranusCheckbox").checked = in_array("9",planetsArray);
  $("toggleNeptuneCheckbox").checked = in_array("10",planetsArray);
  $("togglePlutoCheckbox").checked = in_array("11",planetsArray);
  $("toggleChironCheckbox").checked = in_array("12",planetsArray);
  $("toggleNodeCheckbox").checked = in_array("19",planetsArray);

  $("toggleConjunctionCheckbox").checked = in_array("48",aspectsArray);
  $("toggleOppositionCheckbox").checked = in_array("49",aspectsArray);
  $("toggleTrineCheckbox").checked = in_array("50",aspectsArray);
  $("toggleSquareCheckbox").checked = in_array("51",aspectsArray);
  $("toggleSextileCheckbox").checked = in_array("52",aspectsArray);
  $("toggleQuincunxCheckbox").checked = in_array("56",aspectsArray);
  $("toggleSolarCheckbox").checked = in_array("69",aspectsArray);
  $("toggleLunarCheckbox").checked = in_array("70",aspectsArray);
  $("toggleSignCheckbox").checked = in_array("71",aspectsArray);
  $("toggleDirectCheckbox").checked = in_array("72",aspectsArray);
  $("toggleRetrogradeCheckbox").checked = in_array("73",aspectsArray);
  
  if (relativeDates == 1) $("relativeDateCheckbox").checked = true;
  else $("relativeDateCheckbox").checked = false;
}

//Updates the transit list according to the checkboxes
function customizeTransitList() {
  planets = "";
  aspects = "";
  
  if ($("toggleLunarCheckbox").checked) planets = planets+"1,";
  if ($("toggleSunCheckbox").checked) planets = planets+"2,";
  if ($("toggleMercuryCheckbox").checked) planets = planets+"4,";
  if ($("toggleVenusCheckbox").checked) planets = planets+"5,";
  if ($("toggleMarsCheckbox").checked) planets = planets+"6,";
  if ($("toggleJupiterCheckbox").checked) planets = planets+"7,";
  if ($("toggleSaturnCheckbox").checked) planets = planets+"8,";
  if ($("toggleUranusCheckbox").checked) planets = planets+"9,";
  if ($("toggleNeptuneCheckbox").checked) planets = planets+"10,";
  if ($("togglePlutoCheckbox").checked) planets = planets+"11,";
  if ($("toggleChironCheckbox").checked) planets = planets+"12,";
  if ($("toggleNodeCheckbox").checked) planets = planets+"19,";
  planets = planets.substring(0,planets.lastIndexOf(','));
  
  if ($("toggleConjunctionCheckbox").checked) aspects = aspects+"48,";
  if ($("toggleOppositionCheckbox").checked) aspects = aspects+"49,";
  if ($("toggleTrineCheckbox").checked) aspects = aspects+"50,";
  if ($("toggleSquareCheckbox").checked) aspects = aspects+"51,";
  if ($("toggleSextileCheckbox").checked) aspects = aspects+"52,";
  if ($("toggleQuincunxCheckbox").checked) aspects = aspects+"56,";
  if ($("toggleSolarCheckbox").checked) aspects = aspects+"69,";
  if ($("toggleLunarCheckbox").checked) aspects = aspects+"70,";
  if ($("toggleSignCheckbox").checked) aspects = aspects+"71,";
  if ($("toggleDirectCheckbox").checked) aspects = aspects+"72,";
  if ($("toggleRetrogradeCheckbox").checked) aspects = aspects+"73,";
  aspects = aspects.substring(0,aspects.lastIndexOf(','));  
  
  if ($("relativeDateCheckbox").checked) relativeDates = 1;
  else relativeDates = 0;
  
  getTransits();
}

/******************************************************************************/
/************************* CHART ANIMATION FUNCTIONS **************************/
/******************************************************************************/

//Run on every keystroke while the user is manually inputting time, validates date and updates chart
function checkUserDate(event) {
  //Find the key that was pressed. If Enter, reformat the date text area
  if(window.event) keynum = window.event.keyCode;
  else if(event.which) keynum = event.which;

  //Dynamically check the validity of the date as the user types and indicate with red/black text
  var keynum, validDateArray = parseDateString(document.getElementById("userdate").value);
  if (!validDateArray) {
    document.getElementById("userdate").style.color = "red";
    if (userDateTimeOutActive) {
      clearTimeout(userDateTimeOutID);
      userDateTimeOutActive = false;
    }
  }
  else {
    document.getElementById("userdate").style.color = "black";
    dateInfo['charts'][1] = validDateArray;
    userDateTimeOutActive = true;
    userDateTimeOutID = setTimeout("updateChart()",2000)
  }
  if (keynum == 13 || keynum == 9) {
    document.getElementById("userdate").style.color = "black";
    document.getElementById("userdate").value = dateInfo['charts'][1]['localString'];
    document.getElementById("userdate").select();
  }
  return false;
}

//Start a timer in case the user holds down one of the animation buttons
function incrementChartStart(incA,incI) {
  incInterval = incI;
  incAmount = incA;
  incrementChart();
  if (userDateTimeOutActive) {
    userDateTimeOutActive = false;
    clearTimeout(userDateTimeOutID);
  }
  if (!incrementChartTimerActive) {
    incrementChartTimerID = setInterval("incrementChart()",200);
    incrementChartTimerActive = true;
    document.getElementById("userdate").style.fontWeight = "bold"
    document.getElementById("userdate").style.color = "#009900"
  }
  return false;
}

//This function is called by the timer and updates the text portion of the display
function incrementChart() {
  var timeDiff, newTimestamp;
  switch(incInterval) {
    case "hr":
      timeDiff = incAmount * (60*60);
      break;    
    case "day":
      timeDiff = incAmount * (60*60*24);
      break;
    case "mn":
      timeDiff = incAmount * (60*60*24*30);
      break;
    case "yr":
      timeDiff = incAmount * (60*60*24*365);
      break;
  }
  newTimestamp = dateInfo['charts'][1]['timestamp'] + timeDiff;
  dateInfo['charts'][1] = extractTimestamp(newTimestamp);
  document.getElementById("userdate").value = dateInfo['charts'][1]['localString'];
  return false;
}

//This function concludes the timer and updates the chart with the newly inputted date
function incrementChartEnd() {
  if (incrementChartTimerActive) {
    incrementChartTimerActive = false;
    clearTimeout(incrementChartTimerID);
    document.getElementById("userdate").style.fontWeight = "normal"
    document.getElementById("userdate").style.color = "black"
  }
  userDateTimeOutActive = true;
  userDateTimeOutID = setTimeout("updateChart()",500);
  return false;
}

/******************************************************************************/
/***************************** DISPLAY FUNCTIONS ******************************/
/******************************************************************************/

//Set the various page elements to fit the window on initial load and after every resize
function setLayout() {
  function getWindowSize() {
    if( typeof( window.innerWidth ) == 'number' ) {
      //Non-IE
      windowWidth = window.innerWidth;
      windowHeight = window.innerHeight;
    } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
      //IE 6+ in 'standards compliant mode'
      windowWidth = document.documentElement.clientWidth;
      windowHeight = document.documentElement.clientHeight;
    } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
      //IE 4 compatible
      windowWidth = document.body.clientWidth;
      windowHeight = document.body.clientHeight;
    }
  }
  getWindowSize();
  
  //Determine when to show the right Div
  if (windowWidth <= 754) var noRight = true;
  else var noRight = false;
  if (noRight) {
    rightWidth = 0;
    document.getElementById("right").style.visibility = "hidden";
  }
  else {
    rightWidth = 200;
    document.getElementById("right").style.visibility = "visible";
  }
  
  //Determine when to show the left Div
  if (windowWidth <= 554) var noLeft = true;
  else var noLeft = false;
  if (noLeft) {
    leftWidth = 2;
    document.getElementById("left").style.visibility = "hidden";
  }
  else {
    leftWidth = 200;
    document.getElementById("left").style.visibility = "visible";
  }
  
  //Determine when to show the header Div
  if (windowHeight <= 550) var noHeader = true;
  else var noHeader = false;
  if (noHeader) {
    headerHeight = 2;
    document.getElementById("header").style.visibility = "hidden";
  }
  else {
    headerHeight = 100;
    document.getElementById("header").style.visibility = "visible";
  }
  
  //Set div elements' size and position
  if (!noHeader) Position.set('header',0,0,windowWidth-4,headerHeight-2);
  if (!noLeft) Position.set('left',0,headerHeight-2,leftWidth-2,windowHeight-headerHeight-2);
  Position.set('middle',leftWidth-2,headerHeight-2,windowWidth-leftWidth-rightWidth-2,windowHeight-headerHeight-2);
  var middleDiv = Position.get('middle');
  if (!noRight) Position.set('right',leftWidth+middleDiv.width-2,headerHeight-2,rightWidth-2,windowHeight-headerHeight-2);
  
  //Set chart wheel size
  if (middleDiv.width < middleDiv.height) chartSize = middleDiv.width;
  else chartSize = middleDiv.height;
  chartSize = chartSize-52;
  document.getElementById("chartWheel").width = chartSize;
  document.getElementById("chartWheel").height = chartSize;
  updateChart();
  
  //Set max transits
  max = Math.floor(($("left").getHeight()-100)/27);
  return false;
}

//Update the clock in the top corner without updating the date array (ie - extractDateObject)
function updateCurrentDate() {
  dateInfo['charts'][0]['dateObject'] = new Date();
  changeTextById("currentdate",dateInfo['charts'][0]['dateObject'].toLocaleString());
  return false;
}

//Pause or unpause the clock in the top corner
function toggleCurrentDateTimer() {
  dateInfo['charts'][0] = extractDateObject(new Date());
  if (currentDateTimerActive) {
    currentDateTimerActive = false;
    changeTextById("pauselink"," continue");
    clearInterval(currentDateTimerID);
  }
  else {
    currentDateTimerActive = true;
    changeTextById("pauselink"," pause");
    currentDateTimerID = setInterval("updateCurrentDate()",1000);
  }
  return false;
}

/******************************************************************************/
/*************************** EMAIL FORM FUNCTIONS *****************************/
/******************************************************************************/

//Sign up for email list ajax form submission function
function emailList() {
  var emailaddress = document.getElementById("emailaddress1").value;
  if (echeck(emailaddress))
    new Ajax.Request('emaillist.php', {
      parameters: $('emaillist').serialize(true),
      onSuccess: function(transport){
        var response = transport.responseText || "I'm not sure what just happened...";
        alert(response);
        $('emailaddress1').value = "";
      },
      onFailure: function(){ alert('Something went wrong...') }
    });
  else {
    alert("Incorrect email address!");
  }
  return false;
}

//Contact me ajax form submission function
function contactForm() {
  var emailaddress = document.getElementById("emailaddress2").value;
  if (echeck(emailaddress))
    new Ajax.Request('emaillist.php', {
      parameters: $('contactform').serialize(true),
      onSuccess: function(transport){
        var response = transport.responseText || "I'm not sure what just happened...";
        $('contactformBox').style.display = 'none';
        alert(response);
      },
      onFailure: function(){ alert('Something went wrong...') }
    });
  else {
    alert("incorrect email address!");
  }
  return false;
}

//Check the validity of email address
function echeck(str) {
  var at="@";
  var dot=".";
  var lat=str.indexOf(at);
  var lstr=str.length;
  var ldot=str.indexOf(dot);
  
  if (str.indexOf(at)==-1) return false;
  if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr) return false;
  if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr) return false;
  if (str.indexOf(at,(lat+1))!=-1) return false;
  if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot) return false;
  if (str.indexOf(dot,(lat+2))==-1) return false;
  if (str.indexOf(" ")!=-1) return false;
  return true					
}

/******************************************************************************/
/******************** INITIALIZATION AND MISC FUNCTIONS ***********************/
/******************************************************************************/

//Call this function only when the page is first loaded
function initialize() {
  try {
		registerEventHandlers();
	  var dateObject = new Date(), userTimestamp = location.hash.replace(/#/,"");
	  dateInfo['charts'][0] = extractDateObject(dateObject);
	  if (typeof(userTimestamp)=="number" || !isNaN(parseInt(userTimestamp))) dateObject.setTime(parseInt(userTimestamp*1000));
	  dateInfo['charts'][1] = extractDateObject(dateObject);
	  buildCalendar();
	  setLayout();
	  getTransits("update");
	  document.getElementById("userdate").value = dateInfo['charts'][1]['localString'];
	  //Determine whether or not innerText property exists for compatibility reasons
	  hasInnerText = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;
	  //currentDateTimerID = setInterval("updateCurrentDate()",1000);
	  //currentDateTimerActive = false;
	  browserAlert();
	  new Ajax.Request('track.php', {
	    method: 'post',
	    parameters: {jstz: dateInfo['charts'][0]['tzOffset'], 
	                jsts: dateInfo['charts'][0]['timestamp'], 
	                jsrf: document.referrer, 
	                jsww: windowWidth, 
	                jswh: windowHeight, 
	                jssw: screen.width, 
	                jssh: screen.height, 
	                jscs: chartSize, 
	                jsls: dateInfo['charts'][0]['dateObject'].toDateString(), 
	                jsus: dateInfo['charts'][0]['UTCFullString'] }
	  });
  }
  catch (e) {
	  new Ajax.Request('error.php', {
	    method: 'post',
	    parameters: {e:e.message}
	  });
  }
}

function registerEventHandlers() {
  document.getElementById("permalink").onclick = setPermalink;
  document.getElementById("contact").onclick = function () {$('contactformBox').style.display='block';$('emailaddress2').focus();}
  document.getElementById("currentchartlink").onclick = showCurrentChart;
  document.getElementById("userdate").onkeyup = checkUserDate;
  document.getElementById("userdate").onfocus = function () {this.select();}
  document.getElementById("emaillist").onsubmit = emailList;
  document.getElementById("contactform").onsubmit = contactForm;
  $$('.closeButton').each(function(eachObject) { Event.observe(eachObject,'click',function() {
    this.parentNode.style.display='none';
  }); });
  
  //Chart Animation Buttons
  document.getElementById("hrF").onmousedown = function () {incrementChartStart(1,'hr');}
  document.getElementById("hrF").onmouseup = incrementChartEnd;
  document.getElementById("hrF").onmouseout = incrementChartEnd;
  document.getElementById("hrB").onmousedown = function () {incrementChartStart(-1,'hr');}
  document.getElementById("hrB").onmouseup = incrementChartEnd;
  document.getElementById("hrB").onmouseout = incrementChartEnd;
  
  document.getElementById("dayF").onmousedown = function () {incrementChartStart(1,'day');}
  document.getElementById("dayF").onmouseup = incrementChartEnd;
  document.getElementById("dayF").onmouseout = incrementChartEnd;
  document.getElementById("dayB").onmousedown = function () {incrementChartStart(-1,'day');}
  document.getElementById("dayB").onmouseup = incrementChartEnd;
  document.getElementById("dayB").onmouseout = incrementChartEnd;
  
  document.getElementById("mnF").onmousedown = function () {incrementChartStart(1,'mn');}
  document.getElementById("mnF").onmouseup = incrementChartEnd;
  document.getElementById("mnF").onmouseout = incrementChartEnd;
  document.getElementById("mnB").onmousedown = function () {incrementChartStart(-1,'mn');}
  document.getElementById("mnB").onmouseup = incrementChartEnd;
  document.getElementById("mnB").onmouseout = incrementChartEnd;
  
  document.getElementById("yrF").onmousedown = function () {incrementChartStart(1,'yr');}
  document.getElementById("yrF").onmouseup = incrementChartEnd;
  document.getElementById("yrF").onmouseout = incrementChartEnd;
  document.getElementById("yrB").onmousedown = function () {incrementChartStart(-1,'yr');}
  document.getElementById("yrB").onmouseup = incrementChartEnd;
  document.getElementById("yrB").onmouseout = incrementChartEnd;
}

//Get url parameter by name
function gup(name) {
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if (results == null) return "";
  else return results[1];
}

//Set the timestamp of the active chart to the hash field of the url
function setPermalink() {
  location.hash = dateInfo['charts'][1]['timestamp'];
  $('permalinkTextbox').value = window.location;
  $('permalinkBox').style.display = "block";
  $('permalinkTextbox').focus();
  $('permalinkTextbox').select();
  return false;
}

//Change the text inside any element 
function changeTextById(elementId,changeVal){
  var elem = document.getElementById(elementId);
  if(!hasInnerText) elem.textContent = changeVal;
  else elem.innerText = changeVal;
  return false;
}

//Check to see if a string is contained in an array
function in_array(string, array) {
  for(var i=0; i<array.length; i++) {
    if (array[i] == string) return true;
  }
  return false;
}

//Check the version of the browser and display an alert in the "errorBox" if necessary
function browserAlert() {
  if (BrowserDetect.browser == "Explorer" && BrowserDetect.version == 6) {
    $("errorBox").innerHTML = 'You are using IE6. Please <a href="http://www.microsoft.com/ie" target="_blank">upgrade</a> for better performance, or try <a href="http://www.mozilla.com" target="_blank">Firefox</a> or <a href="http://www.google.com/chrome" target="_blank">Chrome</a>. <a href="#" style="font-size:9px;vertical-align:top;font-weight:bold;" onclick="changeTextById(\'errorBox\',\'\');return false;">X</a>';
  }
}

/* Browser detect script
 * http://www.quirksmode.org/js/detect.html
 * Browser name:      BrowserDetect.browser
 * Browser version:   BrowserDetect.version
 * OS name:           BrowserDetect.OS
 */
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			   string: navigator.userAgent,
			   subString: "iPhone",
			   identity: "iPhone/iPod"
	    },
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

window.onload = initialize;
window.onresize = setLayout;

