// Javascript Lunar Eclipse Explorer//// This code is being released under the terms of the GNU General Public// License (http://www.gnu.org/copyleft/gpl.html) with the request // that if you do improve on it or use it in your own site, // please let us know at// chris@obyrne.com  and  espenak@gsfc.nasa.gov    Thanks!////http://sunearth.gsfc.nasa.gov/eclipse/JLEX/JLEX-index.html///*Javascript Lunar Eclipse ExplorerVersion 1 by Chris O'Byrne and Fred Espenak - 2007 May 23.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.*///// Observer constants -// (0) North Latitude (radians)// (1) West Longitude (radians)// (2) Altitude (metres)// (3) West time zone (hours)// (4) index into the elements array for the eclipse in question// (5) maximum eclipse type//var obsvconst = new Array();//// Eclipse circumstances//  (0) Event type (p1=-3, u1=-2, u2=-1, mid=0, u3=1, u4=2, p4=3)//  (1) t//  (2) hour angle//  (3) declination//  (4) alt//  (5) visibility//      (0 = above horizon, 1 = no event, 2 = below horizon)//var month = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul",                      "Aug","Sep","Oct","Nov","Dec");var p1 = new Array();var u1 = new Array();var u2 = new Array();var mid = new Array();var u3 = new Array();var u4 = new Array();var p4 = new Array();var currenttimeperiod = "";var loadedtimeperiods = new Array();//// Populate the circumstances array// entry condition - circumstances[1] must contain the correct valuefunction populatecircumstances(elements, circumstances) {  var index, t, ra, dec, h;  index = obsvconst[4]  t = circumstances[1]  ra = elements[18+index] * t + elements[17+index]  ra = ra * t + elements[16+index]  dec = elements[21+index] * t + elements[20+index]  dec = dec * t + elements[19+index]  dec = dec * Math.PI / 180.0  circumstances[3] = dec  h = 15.0*(elements[6+index] + (t - elements[2+index]/3600.0)*1.00273791) - ra  h = h * Math.PI / 180.0 - obsvconst[1]  circumstances[2] = h  circumstances[4] = Math.asin(Math.sin(obsvconst[0]) * Math.sin(dec) + Math.cos(obsvconst[0]) * Math.cos(dec) * Math.cos(h))  circumstances[4] -= Math.asin(Math.sin(elements[7+index]*Math.PI/180.0) * Math.cos(circumstances[4]))  if (circumstances[4] * 180.0 / Math.PI < elements[8+index] - 0.5667) {    circumstances[5] = 2  } else if (circumstances[4] < 0.0) {    circumstances[4] = 0.0    circumstances[5] = 0  } else {    circumstances[5] = 0  }}//// Populate the p1, u1, u2, mid, u3, u4 and p4 arraysfunction getall(elements) {  var pattern, index  index = obsvconst[4]  p1[1] = elements[index+9]  populatecircumstances(elements,p1)  mid[1] = elements[index+12]  populatecircumstances(elements,mid)  p4[1] = elements[index+15]  populatecircumstances(elements,p4)  if (elements[index+5] < 3) {    u1[1] = elements[index+10]    populatecircumstances(elements,u1)    u4[1] = elements[index+14]    populatecircumstances(elements,u4)    if (elements[index+5] < 2) {      u2[1] = elements[index+11]      u3[1] = elements[index+13]      populatecircumstances(elements,u2)      populatecircumstances(elements,u3)    } else {      u2[5] = 1      u3[5] = 1    }  } else {    u1[5] = 1    u2[5] = 1    u3[5] = 1    u4[5] = 1  }  if ((p1[5] != 0) && (u1[5] != 0) && (u2[5] != 0) && (mid[5] != 0) && (u3[5] != 0) && (u4[5] != 0) && (p4[5] != 0)) {    mid[5] = 1  }}//// Read the data that's in the form, and populate the obsvconst arrayfunction readform() {  var tmp  // Make sure that we have something to parse from the form  if (document.eclipseform.latd.value == "") document.eclipseform.latd.value="0"  if (document.eclipseform.latm.value == "") document.eclipseform.latm.value="0"  if (document.eclipseform.lats.value == "") document.eclipseform.lats.value="0"  if (document.eclipseform.lond.value == "") document.eclipseform.lond.value="0"  if (document.eclipseform.lonm.value == "") document.eclipseform.lonm.value="0"  if (document.eclipseform.lons.value == "") document.eclipseform.lons.value="0"  if (document.eclipseform.alt.value == "") document.eclipseform.alt.value="0"  // Write back to the form what we are parsing  document.eclipseform.latd.value=Math.abs(parseFloat(document.eclipseform.latd.value))  document.eclipseform.latm.value=Math.abs(parseFloat(document.eclipseform.latm.value))  document.eclipseform.lats.value=Math.abs(parseFloat(document.eclipseform.lats.value))  document.eclipseform.lond.value=Math.abs(parseFloat(document.eclipseform.lond.value))  document.eclipseform.lonm.value=Math.abs(parseFloat(document.eclipseform.lonm.value))  document.eclipseform.lons.value=Math.abs(parseFloat(document.eclipseform.lons.value))  document.eclipseform.alt.value=Math.abs(parseFloat(document.eclipseform.alt.value))  // Get the latitude  obsvconst[0]=parseFloat(document.eclipseform.latd.value)+parseFloat(document.eclipseform.latm.value)/60.0+parseFloat(document.eclipseform.lats.value)/3600.0  obsvconst[0]=obsvconst[0]*parseFloat(document.eclipseform.latx.options[document.eclipseform.latx.selectedIndex].value)  obsvconst[0]=obsvconst[0]*Math.PI/180.0  // Get the longitude  obsvconst[1]=parseFloat(document.eclipseform.lond.value)+parseFloat(document.eclipseform.lonm.value)/60.0+parseFloat(document.eclipseform.lons.value)/3600.0  obsvconst[1]=obsvconst[1]*parseFloat(document.eclipseform.lonx.options[document.eclipseform.lonx.selectedIndex].value)  obsvconst[1]=obsvconst[1]*Math.PI/180.0  // Get the altitude  obsvconst[2]=parseFloat(document.eclipseform.alt.value)  // Get the time zone  obsvconst[3]=parseFloat(document.eclipseform.tzm.options[document.eclipseform.tzm.selectedIndex].value)  obsvconst[3]=parseFloat(document.eclipseform.tzh.options[document.eclipseform.tzh.selectedIndex].value) + obsvconst[3]/60.0  obsvconst[3]=parseFloat(document.eclipseform.tzx.options[document.eclipseform.tzx.selectedIndex].value) * obsvconst[3]  obsvconst[4] = 0  for (tmp = 0 ; tmp < 3 ; tmp++) {    if (document.eclipseform.ecltype[tmp].checked) {      obsvconst[5] = document.eclipseform.ecltype[tmp].value    }  }}//// Get the local date of an eventfunction getdate(elements,circumstances) {  var t, ans, jd, a, b, c, d, e, index  index = obsvconst[4]  // Calculate the JD for noon (TDT) the day before the day that contains T0  jd = Math.floor(elements[index] - (elements[1+index]/24.0))  // Calculate the local time (ie the offset in hours since midnight TDT on the day containing T0).  t = circumstances[1] + elements[1+index] - obsvconst[3] - (elements[2+index] - 30.0) / 3600.0  if (t < 0.0) {    jd--;  }  if (t >= 24.0) {    jd++;  }  if (jd >= 2299160.0) {    a = Math.floor((jd - 1867216.25) / 36524.25)    a = jd + 1 + a - Math.floor(a/4);  } else {    a = jd;  }  b = a + 1525.0  c = Math.floor((b-122.1)/365.25)  d = Math.floor(365.25*c)  e = Math.floor((b - d) / 30.6001)  d = b - d - Math.floor(30.6001*e)  if (e < 13.5) {    e = e - 1  } else {    e = e - 13  }  if (e > 2.5) {    ans = c - 4716 + "-"  } else {    ans = c - 4715 + "-"  }  ans += month[e-1] + "-"  if (d < 10) {    ans = ans + "0"  }  ans = ans + d  return ans}//// Get the local time of an eventfunction gettime(elements,circumstances) {  var t, ans, index, html, ital  ans = ""  index = obsvconst[4]  t = circumstances[1] + elements[1+index] - obsvconst[3] - (elements[2+index] - 30.0) / 3600.0  if (t < 0.0) {    t = t + 24.0  }  if (t >= 24.0) {    t = t - 24.0  }  if (t < 10.0) {    ans = ans + "0"  }  ans = ans + Math.floor(t) + ":"  t = (t * 60.0) - 60.0 * Math.floor(t)  if (t < 10.0) {    ans = ans + "0"  }  ans = ans + Math.floor(t)  if (circumstances[5] == 2) {    html = document.createElement("font");    html.setAttribute("color","#808080");    ital = document.createElement("i");    ital.appendChild(document.createTextNode(ans));    html.appendChild(ital);    return html;  } else {    return document.createTextNode(ans);  }}//// Get the altitudefunction getalt(circumstances) {  var t, ans, html, ital  t = circumstances[4] * 180.0 / Math.PI  t = Math.floor(t+0.5)  if (t < 0.0) {    ans = "-"    t = -t  } else {    ans = "+"  }  if (t < 10.0) {    ans = ans + "0"  }  ans = ans + t  if (circumstances[5] == 2) {    html = document.createElement("font");    html.setAttribute("color","#808080");    ital = document.createElement("i");    ital.appendChild(document.createTextNode(ans));    html.appendChild(ital);    return html;  } else {    return document.createTextNode(ans);  }}function clearoldresults() {  results = document.getElementById("el_results");  resultsTable = document.getElementById("el_locationtable");  if (resultsTable != null) results.removeChild(resultsTable);  resultsTable = document.getElementById("el_resultstable");  if (resultsTable != null) results.removeChild(resultsTable);}// CALCULATE!function calculatefor(el) {  readform()  clearoldresults();  results = document.getElementById("el_results");  p = document.createElement("p");  p.setAttribute("id","el_locationtable");  b = document.createElement("h2");  b.setAttribute("align","center");  b.appendChild(document.createTextNode("Lunar Eclipses from "+el[0]));  p.appendChild(b);  b = document.createElement("h2");  b.setAttribute("align","center");  b.appendChild(document.createTextNode(document.eclipseform.loc_name.value));  p.appendChild(b);  resultsTable = document.createElement("table");  resultsTable.setAttribute("border","0");  tbody = document.createElement("tbody");  row = document.createElement("tr");  td = document.createElement("td");  td.setAttribute("align","right");  td.setAttribute("nowrap","");  td.appendChild(document.createTextNode("Latitude: "));  row.appendChild(td);  td = document.createElement("td");  td.setAttribute("nowrap","");  text = document.eclipseform.latd.value;  text += "\u00b0 ";  if (document.eclipseform.latm.value < 10) text += "0";  text += document.eclipseform.latm.value;  text += "' ";  if (document.eclipseform.lats.value < 10) text += "0";  text += document.eclipseform.lats.value;  text += '" ';  text += (document.eclipseform.latx.options[document.eclipseform.latx.selectedIndex]).text;  td.appendChild(document.createTextNode(text));  row.appendChild(td);  tbody.appendChild(row);  row = document.createElement("tr");  td = document.createElement("td");  td.setAttribute("align","right");  td.setAttribute("nowrap","");  td.appendChild(document.createTextNode("Longitude: "));  row.appendChild(td);  td = document.createElement("td");  td.setAttribute("nowrap","");  text = document.eclipseform.lond.value;  text += "\u00b0 ";  if (document.eclipseform.lonm.value < 10) text += "0";  text += document.eclipseform.lonm.value;  text += "' ";  if (document.eclipseform.lons.value < 10) text += "0";  text += document.eclipseform.lons.value;  text += '" ';  text += (document.eclipseform.lonx.options[document.eclipseform.lonx.selectedIndex]).text;  td.appendChild(document.createTextNode(text));  row.appendChild(td);  tbody.appendChild(row);  row = document.createElement("tr");  td = document.createElement("td");  td.setAttribute("align","right");  td.setAttribute("nowrap","");  td.appendChild(document.createTextNode("Altitude: "));  row.appendChild(td);  td = document.createElement("td");  td.setAttribute("nowrap","");  text = document.eclipseform.alt.value;  text += "m";  td.appendChild(document.createTextNode(text));  row.appendChild(td);  tbody.appendChild(row);  row = document.createElement("tr");  td = document.createElement("td");  td.setAttribute("align","right");  td.setAttribute("nowrap","");  td.appendChild(document.createTextNode("Time Zone: "));  row.appendChild(td);  td = document.createElement("td");  td.setAttribute("nowrap","");  text = (document.eclipseform.tzh.options[document.eclipseform.tzh.selectedIndex]).text;  text += ":";  text += (document.eclipseform.tzm.options[document.eclipseform.tzm.selectedIndex]).text;  text += " ";  text += (document.eclipseform.tzx.options[document.eclipseform.tzx.selectedIndex]).text;  td.appendChild(document.createTextNode(text));  row.appendChild(td);  tbody.appendChild(row);  resultsTable.appendChild(tbody);  p.appendChild(resultsTable);  results.appendChild(p);  resultsTable = document.createElement("table");  resultsTable.setAttribute("id","el_resultstable");  resultsTable.setAttribute("width","150");  resultsTable.setAttribute("border","2");  tbody = document.createElement("tbody");  row = document.createElement("tr");  td = document.createElement("th");  td.appendChild(document.createTextNode("Calendar Date"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Ecl. Type"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Pen. Mag."));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Umbral Mag."));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Pen. Eclipse Begins"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Partial Eclipse Begins"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Total Eclipse Begins"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Mid. Eclipse"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Total Eclipse Ends"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Partial Eclipse Ends"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Pen. Eclipse Ends"));  row.appendChild(td);  td = document.createElement("th");  td.appendChild(document.createTextNode("Alt"));  row.appendChild(td);  tbody.appendChild(row);  for (i = 1 ; i < el.length ; i+=22) {   if (el[5+i] <= obsvconst[5]) {    obsvconst[4]=i;    getall(el)    // Is there an event...    if (mid[5] != 1) {      row = document.createElement("tr");      // Calendar Date      td = document.createElement("td");      td.setAttribute("nowrap","")      val = document.createTextNode(getdate(el,p1));      td.appendChild(val);      row.appendChild(td);      // Eclipse Type      td = document.createElement("td");      td.setAttribute("align","center")      if (el[5+i] == 1) {        td.appendChild(document.createTextNode("T"))      } else if (el[5+i] == 2) {        td.appendChild(document.createTextNode("P"))      } else {        td.appendChild(document.createTextNode("N"))      }      row.appendChild(td);      // Pen. Mag      td = document.createElement("td");      td.setAttribute("align","right");      td.appendChild(document.createTextNode(el[3+i]));      row.appendChild(td);      // Umbral Mag      td = document.createElement("td");      td.setAttribute("align","right");      td.appendChild(document.createTextNode(el[4+i]));      row.appendChild(td);      // P1      td = document.createElement("td");      td.setAttribute("align","center")      td.appendChild(gettime(el, p1));      row.appendChild(td)      // P1 alt      td = document.createElement("td");      td.setAttribute("align","center")      td.appendChild(getalt(p1));      row.appendChild(td)      if (u1[5] == 1) {        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);      } else {        // U1        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(gettime(el, u1));        row.appendChild(td)        // U1 alt        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(getalt(u1));        row.appendChild(td)      }      if (u2[5] == 1) {        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);      } else {        // U2        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(gettime(el, u2));        row.appendChild(td)        // U2 alt        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(getalt(u2));        row.appendChild(td)      }      // mid      td = document.createElement("td");      td.setAttribute("align","center")      td.appendChild(gettime(el, mid));      row.appendChild(td)      // mid alt      td = document.createElement("td");      td.setAttribute("align","center")      td.appendChild(getalt(mid));      row.appendChild(td)      if (u3[5] == 1) {        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);      } else {        // u3        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(gettime(el, u3));        row.appendChild(td)        // u3 alt        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(getalt(u3));        row.appendChild(td)      }      if (u4[5] == 1) {        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(document.createTextNode("-"))        row.appendChild(td);      } else {        // u4        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(gettime(el, u4));        row.appendChild(td)        // u4 alt        td = document.createElement("td");        td.setAttribute("align","center")        td.appendChild(getalt(u4));        row.appendChild(td)      }      // P4      td = document.createElement("td");      td.setAttribute("align","center")      td.appendChild(gettime(el, p4));      row.appendChild(td)      // P4 alt      td = document.createElement("td");      td.setAttribute("align","center")      td.appendChild(getalt(p4));      row.appendChild(td)      tbody.appendChild(row);    }   }  }  resultsTable.appendChild(tbody);  results.appendChild(resultsTable);}function init() {  opt = document.getElementById("el_cities");  for (i = 0 ; i < cities.length ; i+=9) {    name = String(cities[i]);    if (name.indexOf("--",0) == 0) {      group = document.createElement("optgroup");      group.setAttribute("label",name.substring(2));      opt.appendChild(group);      i++;    }    city = document.createElement("option");    city.setAttribute("value",i);    cityName = document.createTextNode(cities[i]);    city.appendChild(cityName);    opt.appendChild(city);  }}function citychange() {  clearoldresults();  index = Number(document.eclipseform.cityndx.value);  if (index <= 0) return;  hemisphere=0;  document.eclipseform.loc_name.value = cities[index++];  val = cities[index++];  if (val < 0) { val=-val; hemisphere=1; }  document.eclipseform.latd.value = val;  val = cities[index++];  if (val < 0) { val=-val; hemisphere=1; }  document.eclipseform.latm.value = val;  val = cities[index++];  if (val < 0) { val=-val; hemisphere=1; }  document.eclipseform.lats.value = val;  document.eclipseform.latx.selectedIndex = hemisphere;  hemisphere=0;  val = cities[index++];  if (val < 0) { val=-val; hemisphere=1; }  document.eclipseform.lond.value = val;  val = cities[index++];  if (val < 0) { val=-val; hemisphere=1; }  document.eclipseform.lonm.value = val;  val = cities[index++];  if (val < 0) { val=-val; hemisphere=1; }  document.eclipseform.lons.value = val;  document.eclipseform.lonx.selectedIndex = hemisphere;  document.eclipseform.alt.value=cities[index++];  val = cities[index];  if (val < 0) {    document.eclipseform.tzx.selectedIndex=1;    val = -val;  } else {    document.eclipseform.tzx.selectedIndex=0;  }  document.eclipseform.tzh.selectedIndex = Math.floor(val);  document.eclipseform.tzm.selectedIndex = Math.floor(4*(val-document.eclipseform.tzh.selectedIndex)+0.5);}function newloc() {  document.eclipseform.cityndx.selectedIndex=0;  clearoldresults();}function settimeperiod(timeperiod) {  for (i = 0 ; i < loadedtimeperiods.length ; i++) {    if (loadedtimeperiods[i] == timeperiod) {      if (eval("self."+timeperiod)) {        currenttimeperiod = timeperiod;        eval(timeperiod+"()");      }      return;    }  }  currenttimeperiod = timeperiod;  loadedtimeperiods.push(timeperiod);  head = document.getElementsByTagName("head")[0];  script = document.createElement("script");  script.setAttribute("language","JavaScript");  script.setAttribute("src",timeperiod+".js");  script.type = "text/javascript";  script.defer = false;  head.appendChild(script);}function recalculate() {  eval(currenttimeperiod+"()");}