Dynamic Properties: Forcing a Recalculation | WebReference

Dynamic Properties: Forcing a Recalculation


Dynamic Properties

Forcing a Recalculation

When implementing functional dependencies between properties, it is always a question when to trigger a recalculation following a change in one of the parameters. There are two opposite strategies. One says that you need to recalculate all parameters whenever one of the parameters or variables changes. The other one, sometimes called lazy evaluation, says that you need to compute a parameter only when you have to know its value. In such a methodology, a function is provided in case you want to force the evaluation.

In JavaScript, you can force a recomputation by calling the Document Object's recalc() method:

document.recalc(true);

In our Solar System example, the need to update the location of the planet is implicit. None of the statements uses the top and left parameters of the planets, but the location of the planets in the solar system is determined by these parameters. Hence, to force the update of their location, we call the recalc() method every time interval:

function triggerRecalculation() {
  currentTime = new Date() - timeAt0;
  document.recalc(true);
}

The second reason we need to trigger a recalculation is that the expression we bound to the planets' parameters depends on the time in seconds passed from the initial loading of the page. The time give us a measure of the angle that the planet needs to complete. We need to find out how many seconds have passed every time interval, so we can update the angle (and the planet location) continuously. Here is the functional dependency between the angle and the time, as well as the planet's period length in days:

function angle(periodInDays, t) {
  return ((t / seconds2daysFactor) / periodInDays) % (2 * Math.PI);
}

The planets' xLocation and yLocation depend on the angle. Here is the functional dependency of xLocation:

function xLocation(obj, distanceFactor, daysPerRound, t) {
  return (obj.style.pixelLeft + obj.style.pixelWidth / 2) +
    Math.round(Math.cos(angle(daysPerRound, t)) * distanceFactor
	                           * fRadius * distanceOfEarth);
}

We trigger the evaluation by calling the setInterval() function:


  intervalID = setInterval("triggerRecalculation()",
  frequencyOfRecalc);

An evidence of the dependency between the angle and the time is what happens when we stop the planets' orbiting. It's impossible to move the Sun while planets are orbiting it, so we stop the solar system when the user clicks on the Sun, signaling the start of the dragging. At this point we stop the orbiting by clearing the pointer we set by the setInterval() method, intervalID:

function fnStartStopMoving() {
  if (oSun.moving == true) {
    oSun.moving = false;
    oSun.style.removeExpression("left");
    oSun.style.removeExpression("top");
    intervalID = setInterval("triggerRecalculation()",
      frequencyOfRecalc);
  }
  else { // oSun.moving = false
    oSun.clickOffsetX = event.clientX - oSun.offsetLeft;
    oSun.clickOffsetY = event.clientY - oSun.offsetTop;
    oSun.moving = true;
    clearInterval(intervalID);
  }
}

Notice that after the solar system freezes (upon clicking the Sun in the first time), and after waiting for a while and then clicking again to resume the system, the Earth begins in exactly the same position as if the solar system did not stop at all. The reason is that the planet's angle depends on the time in seconds that passed since the page first loaded, so it does not matter what the Earth did or did not do in the meantime.

Next: How to program the Solar System, Part I

http://www.internet.com

Produced by Yehuda Shiran and Tomer Shiran

Created: July 18, 2000
Revised: July 18, 2000

URL: http://www.webreference.com/js/column65/6.html