Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

...
  • 5 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
BIN  jsjupiter/borderedmoon.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  jsjupiter/grs.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
337 jsjupiter/index.html
View
@@ -0,0 +1,337 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+<meta content="utf-8" http-equiv="encoding">
+
+<title>Javascript Jupiter</title>
+
+<style type="text/css">
+div#jupframe {
+ background: black;
+ color: white;
+ position: relative;
+ width: 99%;
+ height: 100px;
+}
+
+/* All images and labels inside the jupframe are absolutely positioned */
+#jupframe img, #jupframe span {
+ position: absolute; visibility: hidden; z-index: 50
+}
+
+#jupframe span.moonlabel { color: white; top: .3em; }
+
+#jupframe span.shadowlabel { color: yellow; top: 1.1em; }
+
+#jupframe span#grslabel { color: #aaa; font-size: .9em; bottom: .1em; }
+
+</style>
+
+<!-- The code for calculating Jovian moon and GRS positions: -->
+<script type="text/javascript" src="jupiter.js"></script>
+
+<!-- Code specific to displaying on this page: -->
+<script type="text/javascript">
+function screenWidth() {
+ if (window.innerWidth != null)
+ return window.innerWidth;
+ if (document.documentElement.clientWidth)
+ return document.documentElement.clientWidth;
+ return 800;
+}
+
+function placeImage(im, left, top, width, height) {
+ im.style.left = left;
+ if (top) {
+ im.style.top = top;
+ }
+ if (width) {
+ im.width = width;
+ if (height) {
+ im.height = height;
+ } else {
+ im.height = width; // assume square if width but not height specified
+ }
+ }
+ im.style.visibility = "visible";
+}
+
+// Change to a new date:
+function setDate() {
+ drawJupiter(jup, new Date(document.getElementById("thedate").value));
+
+}
+
+function addHours(hrs) {
+ var d = jup.getDate();
+ d.setTime(d.getTime() + 60 * 60 * hrs * 1000);
+ drawJupiter(jup, d);
+}
+
+/*
+function setNewDateIfEnterKey(ev) {
+ var e = ev || event;
+ if (e.keyCode == 13) { // Was it the return/enter key?
+ setDate();
+ }
+ return false; //prevents form from being submitted.
+ }
+}
+ */
+
+// Animate:
+var animating = false;
+var animateTime = 250;
+
+function animateStep() {
+ if (! animating)
+ return;
+ var d = jup.getDate();
+ d.setTime(d.getTime() + 60 * 60 * 1000);
+ drawJupiter(jup, d);
+ setTimeout("animateStep();", animateTime);
+}
+
+function animateFaster(amt) {
+ if (animateTime == 1 && amt < 0) animateTime = 0;
+ animateTime = animateTime - amt;
+ if (animateTime < 1) animateTime = 1;
+ var animspan = document.getElementById("animDelay");
+ animspan.innerHTML = "Delay: " + animateTime + " milliseconds";
+}
+
+function toggleAnimation() {
+ animating = !animating;
+ if (animating) {
+ animateStep();
+ }
+}
+
+function drawJupiter(jup, date) {
+ jup.setDate(date);
+
+ var thedate = document.getElementById("thedate");
+ if (thedate)
+ thedate.value = date;
+
+ var datefield = document.getElementById("datefield");
+ if (datefield)
+ datefield.value = date;
+
+ var width = parseInt(screenWidth() * .99);
+ var halfwidth = width/2;
+ var height = 100;
+ var halfheight = height/2;
+ var jupRadius = 19;
+ var spotWidth = 27 * jupRadius / 30;
+ var spotHeight = 13 * jupRadius / 30;
+
+ // Make sure Jupiter is properly centered:
+ var img = document.getElementById("jupiter");
+ if (img) {
+ placeImage(img, halfwidth - jupRadius, halfheight - jupRadius, jupRadius*2);
+ }
+
+ // The GRS:
+ var coord = jup.getRedSpotXY(80);
+ var img = document.getElementById("grs");
+ var label = document.getElementById("grslabel");
+
+ if (img && !isNaN(coord.x) && !isNaN(coord.y)) {
+ // XXX Need some extra code here to make width smaller if the GRS
+ // XXX is near the limb and foreshortened.
+ var sx = halfwidth + coord.x * jupRadius - spotWidth/2;
+ var sw = spotWidth;
+ var jr = jupRadius * .8; // approx radius at spot's latitude
+ if (sx < halfwidth - jr) {
+ sw = sw - halfwidth - jr - sx;
+ sx = halfwidth - jr
+ } else if (sx + sw > halfwidth + jr) {
+ sw = halfwidth + jr - sx;
+ }
+ placeImage(img, sx, coord.y * jupRadius + halfheight - spotHeight/2,
+ sw, spotHeight);
+ if (label) {
+ placeImage(label, sx);
+ }
+ }
+ else if (img) {
+ img.style.visibility = "hidden";
+ if (label) {
+ label.style.visibility = "hidden";
+ }
+ }
+ else { alert("no grs image"); }
+
+ for (var whichmoon = 0; whichmoon < 4; ++whichmoon) {
+ // First handle the shadow
+ moondata = jup.getMoonXYData(whichmoon);
+
+ img = document.getElementById("shadow" + whichmoon);
+ label = document.getElementById("slabel" + whichmoon);
+ if (img && !isNaN(moondata.shadowx) && !isNaN(moondata.shadowy)) {
+ img.setAttribute("src", "moonshadow.png");
+ var x = moondata.shadowx * jupRadius + halfwidth;
+ placeImage(img, x, moondata.shadowy * jupRadius + halfheight);
+
+ // Place the label too:
+ if (label) {
+ placeImage(label, x);
+ }
+ }
+ else if (img) {
+ img.style.visibility = "hidden";
+ if (label) {
+ label.style.visibility = "hidden";
+ }
+ }
+
+ // Now, with the shadow done, handle the moon itself:
+ img = document.getElementById("moon" + whichmoon);
+ label = document.getElementById("label" + whichmoon);
+ if (img && !isNaN(moondata.moonx) && !isNaN(moondata.moony)) {
+ img.setAttribute("src", "borderedmoon.png");
+ var x = moondata.moonx * jupRadius + halfwidth;
+ placeImage(img, x, moondata.moony * jupRadius + halfheight);
+ if (moondata.farside)
+ img.style.zIndex = 1;
+ else
+ img.style.zIndex = 100;
+
+ // Place the label too:
+ if (label) {
+ placeImage(label, x);
+ }
+ }
+ else if (img) {
+ img.style.visibility = "hidden";
+ if (label) {
+ label.style.visibility = "hidden";
+ }
+ }
+ }
+
+ var upcoming = document.getElementById("upcoming");
+ if (!upcoming) {
+ alert("No place to note upcoming events");
+ return;
+ }
+
+ upcoming.innerHTML = upcomingEvents(date);
+}
+
+</script>
+</head>
+
+<body>
+<h1>Javascript Jupiter</h1>
+
+<p>
+Here are the four bright "Galilean" moons of Jupiter --
+Io, Europa, Ganymede and Callisto -- and their shadows.
+It also shows the approximate position of Jupiter's "great red spot" (GRS).
+
+<p>
+This is a re-implementation of my older
+<a href="/jupiter.html">Java Jupiter</a> page
+using HTML, CSS and Javascript (and nicer graphics).
+
+<p>
+North is up.
+
+<noscript>
+<p>
+<b>
+The moon positions are set using Javascript, which is disabled
+in your browser. You'll need to turn it back on if you want to see
+the current position of Jupiter's moons.
+</b>
+</noscript>
+
+<div id="jupframe">
+<img id="jupiter" src="smalljup.png">
+<img id="grs" src="grs.png">
+<img id="shadow0" src="moonshadow.png">
+<img id="shadow1" src="moonshadow.png">
+<img id="shadow2" src="moonshadow.png">
+<img id="shadow3" src="moonshadow.png">
+<img id="moon0" src="borderedmoon.png">
+<img id="moon1" src="borderedmoon.png">
+<img id="moon2" src="borderedmoon.png">
+<img id="moon3" src="borderedmoon.png">
+<span id="label0" class="moonlabel">I</span>
+<span id="label1" class="moonlabel">E</span>
+<span id="label2" class="moonlabel">G</span>
+<span id="label3" class="moonlabel">C</span>
+<span id="slabel0" class="shadowlabel">I</span>
+<span id="slabel1" class="shadowlabel">E</span>
+<span id="slabel2" class="shadowlabel">G</span>
+<span id="slabel3" class="shadowlabel">C</span>
+<span id="grslabel">GRS</span>
+</div>
+
+<p>
+<!-- Don't wrap these in a form -- it keeps the dates from working
+ when you hit enter. -->
+Or you can set a date explicitly:
+<!--
+ Would make more sense to use a datetime input, but hitting return in it
+ briefly changes the date, then reverts back to the current date.
+<input id="thedate" type="text" onKeyPress="setNewDateIfEnterKey(event);"
+ size=40>
+<br>
+ -->
+<input id="datefield" type="datetime"
+ onChange="drawJupiter(jup, new Date(document.getElementById('datefield').value)); return false;"
+ size=40>
+<input type="button" name="changeDate" value="Recalculate" onClick="setDate();">
+<p>
+<input type="button" name="nextDay" value="-1 day" onClick="addHours(-24);">
+<input type="button" name="nextHour" value="-1 hour" onClick="addHours(-1);">
+<input type="button" name="nextHour" value="-5 min" onClick="addHours(-1/12);">
+<input type="button" name="nextHour" value="+5 min" onClick="addHours(1/12);">
+<input type="button" name="nextHour" value="+1 hour" onClick="addHours(1);">
+<input type="button" name="nextDay" value="+1 day" onClick="addHours(24);">
+<input type="button" name="now" value="Now"
+ onClick="drawJupiter(jup, new Date());">
+<p>
+<input type="button" name="animate" value="Animate"
+ onClick="toggleAnimation();">
+<input type="button" name="faster" value="faster" onClick="animateFaster(50);">
+<input type="button" name="slower" value="slower" onClick="animateFaster(-50);">
+<span id="animDelay">Delay: 250 milliseconds</span>
+
+<p>
+<textarea id="upcoming" readonly cols=280 rows=30></textarea>
+
+<script type="text/javascript">
+/* Call the code that calculates the positions, defined in jupiter.js. */
+var jup = new Jupiter();
+//var date = new Date();
+// Europa should be visible at 19:51 but gone at 19:59; back at 20:06.
+//var date = new Date('Mon Mar 10 2013 19:53:00 GMT-0700 (PDT)');
+//var date = new Date('Mon Mar 10 2013 19:57:00 GMT-0700 (PDT)');
+var date = new Date('Mon Mar 10 2013 20:02:00 GMT-0700 (PDT)');
+//var date = new Date('Sat Nov 10 2012 16:10:00 GMT-0800 (PDT)');
+drawJupiter(jup, date);
+</script>
+
+<hr>
+I use this app on Android with the help of my
+<a href="http://shallowsky.com/software/android/WebClient/">WebClient</a>
+wrapper app.
+<br>
+For older Java phones,
+Miguel Moreto has adapted this code for a neat mobile phone app called
+<a href="http://code.google.com/p/mobilejupiter/">Mobile Jupiter</a>.
+<p>
+<a href="/software/">Akkana's other software</a> |
+<a href="/astro.html">Akkana's Astronomy Page</a> |
+<a href="/">Shallow Sky home</a>
+
+
+</body>
+</html>
+
384 jsjupiter/jupiter.js
View
@@ -0,0 +1,384 @@
+/* -*- Mode: Javascript; js-indent-level: 4; indent-tabs-mode: nil; -*- */
+
+// Javascript code to calculate the position of Jupiter's moons and shadows.
+// Copyright 2009 by Akkana Peck --
+// please share and enjoy under the terms of the GPL v2 or later.
+//
+// Equations come from Jean Meeus, Astronomical Formulae for Calculators.
+
+// Code below is from Jupiter.java and is in the process of being
+// translated to javascript.
+
+function Jupiter()
+{
+ const NUM_MOONS = 4;
+
+ var curdate; // javascript Date object
+ var d; // days since epoch, 1899 Dec 31 12h ET
+
+ // Angles of each of the Galilean satellites, in radians,
+ // expressed relative to each satellite's inferior conjunction:
+ var moonAngles = [NaN, NaN, NaN, NaN];
+ // And their distances from the planet:
+ var moonDist = [NaN, NaN, NaN, NaN];
+
+ // variables we may want later for moon calcs:
+ var psi;
+
+ var delta; // Earth-Jupiter distance
+ var De; // planetocentric ang. dist. of earth from jup. equator
+ var G;
+ var H;
+
+ // latitudes of systems I and II:
+ var lambda1;
+ var lambda2;
+
+ function getDate() {
+ return curdate;
+ }
+ this.getDate = getDate;
+
+ //
+ // Convert an angle (in radians) so that it's between 0 and 2*PI:
+ //
+ function angle(a)
+ {
+ if (a < 10000)
+ return oangle(a);
+ a = a - 2.*Math.PI * parseInt(a / 2. / Math.PI);
+ if (a < 0)
+ a += 2*Math.PI;
+ return a;
+ }
+
+ function oangle(a)
+ {
+ while (a > 2 * Math.PI)
+ a -= 2. * Math.PI;
+ while (a < 0)
+ a += 2. * Math.PI;
+ return a;
+ }
+
+ function setDate(initDate)
+ {
+ // Calculate the position of Jupiter's central meridian,
+ // and the corresponding moonAngle and moonDist arrays;
+ // and system I and system II longitudes;
+ // psi, the Jupiter's phase angle (always btw. -12 and 12 degrees):
+ // and De, the planetocentric angular distance of the earth
+ // from the equator of Jupiter.
+
+ // First, get the number of days since 1899 Dec 31 12h ET.
+ curdate = initDate;
+ var d = getJulianDate(initDate) - 2415020; // days since 1899 Dec 31 12h ET
+
+ // Argument for the long-period term in the motion of Jupiter:
+ var V = angle((134.63 + .00111587 * d) * Math.PI / 180);
+
+ // Mean anomalies of Earth and Jupiter:
+ var M = angle((358.476 + .9856003 * d) * Math.PI / 180);
+ var N = angle((225.328 + .0830853 * d + .33 * Math.sin(V))
+ * Math.PI / 180);
+
+ // Diff between the mean heliocentric longitudes of Earth & Jupiter:
+ var J = angle((221.647 + .9025179 * d - .33 * Math.sin(V))
+ * Math.PI / 180);
+
+ // Equations of the center of Earth and Jupiter:
+ var A = angle((1.916 * Math.sin(M) + .020 * Math.sin(2*M))
+ * Math.PI / 180);
+ var B = angle((5.552 * Math.sin(N) + .167 * Math.sin(2*N))
+ * Math.PI / 180);
+
+ var K = angle(J + A - B);
+
+ // Distances are specified in AU:
+ // Radius vector of the earth:
+ var R = 1.00014 - .01672 * Math.cos(M) - .00014 * Math.cos(2*M);
+ // Radius vector of Jupiter:
+ var r = 5.20867 - .25192 * Math.cos(N) - .00610 * Math.cos(2*N);
+
+ // Earth-Jupiter distance:
+ delta = Math.sqrt(r*r + R*R - 2*r*R*Math.cos(K));
+
+ // Phase angle of Jupiter (always btw. -12 and 12 degrees):
+ psi = Math.asin(R / delta * Math.sin(K));
+
+ // Longitude of system 1:
+ lambda1 = angle((268.28 * 877.8169088 * (d - delta / 173))
+ * Math.PI / 180 + psi - B);
+ // Longitude of system 2:
+ lambda2 = angle((290.28 + 870.1869088 * (d - delta / 173))
+ * Math.PI / 180 + psi - B);
+
+ // calculate the angles of each of the satellites:
+ moonAngles[0] = angle((84.5506 + 203.4058630 * (d - delta / 173))
+ * Math.PI / 180
+ + psi - B);
+ moonAngles[1] = angle((41.5015 + 101.2916323 * (d - delta / 173))
+ * Math.PI / 180
+ + psi - B);
+ moonAngles[2] = angle((109.9770 + 50.2345169 * (d - delta / 173))
+ * Math.PI / 180
+ + psi - B);
+ moonAngles[3] = oangle((176.3586 + 21.4879802 * (d - delta / 173))
+ * Math.PI / 180
+ + psi - B);
+
+ // and the planetocentric angular distance of the earth
+ // from the equator of Jupiter:
+ var lambda = angle((238.05 + .083091 * d + .33 * Math.sin(V))
+ * Math.PI / 180 + B);
+
+ De = ((3.07 * Math.sin(lambda + 44.5 * Math.PI / 180)
+ - 2.15 * Math.sin(psi) * Math.cos(lambda - 24.*Math.PI/180)
+ - 1.31 * (r - delta) / delta
+ * Math.sin(lambda - 99.4 * Math.PI / 180))
+ * Math.PI / 180);
+
+ G = angle((187.3 + 50.310674 * (d - delta / 173)) * Math.PI / 180);
+ H = angle((311.1 + 21.569229 * (d - delta / 173)) * Math.PI / 180);
+
+ // Calculate the distances before any corrections are applied:
+ moonDist[0] = 5.9061 -
+ .0244 * Math.cos(2 * (moonAngles[0] - moonAngles[1]));
+ moonDist[1] = 9.3972 -
+ .0889 * Math.cos(2 * (moonAngles[1] - moonAngles[2]));
+ moonDist[2] = 14.9894 - .0227 * Math.cos(G);
+ moonDist[3] = 26.3649 - .1944 * Math.cos(H);
+
+ // apply some first-order correction terms to the angles:
+ moonAngles[0] = angle(moonAngles[0] +
+ Math.sin(2 * (moonAngles[0] - moonAngles[1]))
+ * .472 * Math.PI / 180);
+ moonAngles[1] = angle(moonAngles[1] +
+ Math.sin(2 * (moonAngles[1] - moonAngles[2]))
+ * 1.073 * Math.PI / 180);
+ moonAngles[2] = angle(moonAngles[2] +
+ Math.sin(G) * .174 * Math.PI / 180);
+ moonAngles[3] = angle(moonAngles[3] +
+ Math.sin(H) * .845 * Math.PI / 180);
+ }
+ /* Make the function public: */
+ this.setDate = setDate;
+
+ function daysBetween(d1, d2) {
+ return ((d2.getTime() - d1.getTime())) / (24.*60.*60.*1000.);
+ }
+
+ function getJulianDate(d) {
+ return (daysBetween(new Date("Jan 1 0:00 PST 1970"), d)
+ + 2440587.83333333333);
+ }
+
+ /* object that has .x and .y */
+ function XYCoord(x, y) {
+ this.x = x || NaN;
+ this.y = y || NaN;
+ }
+
+ //
+ // Returns the moon position in units of Jupiter radii.
+ // Also calculate the shadows, and whether the moon is eclipsed by Jupiter.
+ //
+ function getMoonXYData(whichmoon)
+ {
+ var r = moonDist[whichmoon];
+
+ var moondata = new Object();
+
+ function getShadowXY(angle)
+ {
+ var moonSunAngle = angle - psi;
+ var xy = new XYCoord();
+ xy.x = r * Math.sin(moonSunAngle);
+ xy.y = r * Math.cos(moonSunAngle) * Math.sin(De);
+ return xy;
+ }
+
+ function dist(x, y)
+ {
+ return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ }
+
+ moondata.moonx = r * Math.sin(moonAngles[whichmoon]);
+ moondata.moony = r * Math.cos(moonAngles[whichmoon]) * Math.sin(De);
+
+ s = "moon " + whichmoon;
+ s += "\nDist = " + r;
+ s += "\nmoonAngle = " + moonAngles[whichmoon];
+ s += " = " + moonAngles[whichmoon] * 180. / Math.PI;
+ s += "\nJup phase angle = " + psi;
+ s += " = " + psi * 180. / Math.PI;
+
+ // See whether the moon is on the near side of the planet:
+ if (moonAngles[whichmoon] < Math.PI * .5
+ || moonAngles[whichmoon] > Math.PI * 1.5)
+ {
+ // Since the moon is on the near side, check for shadows
+ // cast by the moon on the planet.
+ s += "\nNear side of the planet";
+ moondata.farside = false;
+
+ xy = getShadowXY(moonAngles[whichmoon]);
+ moondata.shadowx = xy.x;
+ moondata.shadowy = xy.y;
+
+ // Is it hitting the planet? If not, set coords to NaN.
+ // Some day, ought to check for moons eclipsing other moons
+ if (moondata.shadowx < -1. || moondata.shadowx > 1.)
+ moondata.shadowx = moondata.shadowy = NaN;
+ }
+
+ // Is the moon blocked by the planet, so it's invisible?
+ //else if (moondata.moonx < 1. && moondata.moonx > -1.)
+ else if (dist(moondata.moonx, moondata.moony) < 1.)
+ {
+ moondata.farside = true;
+ moondata.moonx = moondata.moony = NaN;
+ s += "\nBlocked by the planet";
+ }
+
+ // Otherwise, it's on the far side.
+ // See if it's eclipsed by the planet's shadow.
+ else {
+ moondata.farside = true;
+ s += "\nFar side of the planet";
+
+ // See if a moon 180 degrees away from this moon's position,
+ // at the same distance, would cast a shadow on the planet.
+ // If so, the actual moon is eclipsed.
+ //atmoslop = 1.0; // .83 might be worth pursuing
+ atmoslop = .9;
+ xy = getShadowXY(angle(moonAngles[whichmoon] + Math.PI));
+ moondata.eclipse = (dist(xy.x, xy.y) < atmoslop);
+ s += "\nActual moon at (" + moondata.moonx + ", " + moondata.moony + ")";
+ s += "\nFake shadow at (" + xy.x + ", " + xy.y + ")";
+ s += "\nDist from center = " + Math.sqrt(xy.x*xy.x + xy.y*xy.y);
+ if (moondata.eclipse)
+ s += "\nEclipse of moon " + whichmoon + "!";
+
+ /* This was just for testing.
+ if (moondata.eclipse) {
+ moondata.shadowx = xy.x;
+ moondata.shadowy = xy.y;
+ }
+ */
+ }
+
+ //if (moondata.eclipse) alert(s);
+ return moondata;
+ }
+ this.getMoonXYData = getMoonXYData
+
+ //
+ // The Great Red Spot, currently at longitude 61 in system II
+ //
+ function getRedSpotXY(spot_in_deg)
+ {
+ var spotlong = angle(lambda2 - spot_in_deg*Math.PI/180);
+
+ var coord = new XYCoord();
+
+ // See if the spot is visible:
+ if (spotlong > Math.PI * .5 && spotlong < Math.PI * 1.5) {
+ coord.x = coord.y = NaN;
+ } else {
+ coord.x = Math.sin(spotlong);
+ coord.y = .42; // completely random wild-assed guess
+ }
+
+ return coord;
+ }
+ this.getRedSpotXY = getRedSpotXY;
+
+ //
+ // You might also want to get the location of some arbitrary
+ // other position on the planet, e.g. the Great Northern Spot.
+ //
+ function getJovianPointX(long_in_deg, systm)
+ {
+ var lambda = (systm == 1 ? lambda1 : lambda2);
+ var longInRad = angle(lambda - long_in_deg*Math.PI/180);
+
+ // See if the point is visible:
+ if (longInRad > Math.PI * .5 && longInRad < Math.PI * 1.5) {
+ return NaN;
+ } else {
+ return Math.sin(longInRad);
+ }
+ }
+}
+
+function upcomingEvents(date)
+{
+ var saveDate = jup.curdate;
+ if (!saveDate) {
+ //alert("upcoming events, but curdate is " + jup.curdate);
+ saveDate = date;
+ }
+
+ tothrs = 8;
+ interval = 1; // minutes
+ upcoming = "Moon events in the next " + tothrs + " hours:\n";
+
+ moonnames = [ "Io", "Europa", "Ganymede", "Callisto" ];
+
+ d = new Date(date);
+ lastmoondata = [ null, null, null, null ];
+ // Moon data includes moonx, moony, shadowx, shadowy, farside, and eclipsed.
+
+ var verbose = false;
+
+ for (mins = -30; mins < tothrs * 60; mins += interval) {
+ d.setTime(date.getTime() + mins * 60 * 1000);
+ jup.setDate(d);
+ if (verbose)
+ upcoming += "\n" + d + "\n";
+ for (var whichmoon = 0; whichmoon < 4; ++whichmoon) {
+ moondata = jup.getMoonXYData(whichmoon);
+ if (verbose) {
+ upcoming += " (" + whichmoon + "):\n";
+ upcoming += JSON.stringify(moondata) + "\n";
+ }
+ if (lastmoondata[whichmoon]) {
+
+ if (!moondata.moonx && lastmoondata[whichmoon].moonx)
+ upcoming += d + ": "
+ + moonnames[whichmoon] + " disappears\n";
+ else if (moondata.moonx && ! lastmoondata[whichmoon].moonx) {
+ if (! moondata.eclipse)
+ upcoming += d + ": "
+ + moonnames[whichmoon] + " reappears\n";
+ }
+
+ else if (moondata.eclipse && ! lastmoondata[whichmoon].eclipse)
+ upcoming += d + ": " + moonnames[whichmoon]
+ + " enters eclipse\n";
+ else if (! moondata.eclipse && lastmoondata[whichmoon].eclipse)
+ upcoming += d + ": " + moonnames[whichmoon]
+ + " leaves eclipse\n";
+
+ if (!moondata.shadowx && lastmoondata[whichmoon].shadowx)
+ upcoming += d + ": " + moonnames[whichmoon]
+ + "'s shadow disappears\n";
+ else if (moondata.shadowx && !lastmoondata[whichmoon].shadowx)
+ upcoming += d + ": " + moonnames[whichmoon]
+ + "'s shadow reappears\n";
+
+ if (verbose)
+ upcoming += JSON.stringify(lastmoondata[whichmoon]) + "\n"
+ }
+
+ // Ick! This is supposedly the most efficient way to clone
+ // an object in javascript. Can you believe it?
+ lastmoondata[whichmoon] = JSON.parse(JSON.stringify(moondata));
+ }
+ }
+
+ if (saveDate != undefined)
+ jup.setDate(saveDate);
+ return upcoming;
+}
BIN  jsjupiter/moon.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  jsjupiter/moonshadow.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  jsjupiter/smalljup.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

No commit comments for this range

Something went wrong with that request. Please try again.