0

I'm reading DOM Scripting and have a beginner question about the abstraction below. The original code didn't include "clearTimeout", and "movement" was declared as a global variable. While the code ran fine, it wasn't a smooth animation which is why clearTimeout was added. My question however, is why I can't just test for "movement" and when it fails (on the first mouseover call to moveElement) continue on through the rest of the function? If I keep "movement" as a global variable, rather than make it a property, the code doesn't run at all?

If it helps to see the other JS and HTML, I've plugged the remaining code into jsFiddle.

function moveElement(elementID,final_x,final_y,interval) {
  if (!document.getElementById) return false;
  if (!document.getElementById(elementID)) return false;
  var elem = document.getElementById(elementID);
  if (elem.movement) { //Why can't I use "movement"?
    clearTimeout(elem.movement);
  }
  var xpos = parseInt(elem.style.left);
  var ypos = parseInt(elem.style.top);

  if (xpos == final_x && ypos == final_y) {
    return true;
  }
  if (xpos < final_x) {
    xpos++;
  }
  if (xpos > final_x) {
    xpos--;
  }
  if (ypos < final_y) {
    ypos++;
  }
  if (ypos > final_y) {
    ypos--;
  }
  elem.style.left = xpos + "px";
  elem.style.top = ypos + "px";
  var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
  elem.movement = setTimeout(repeat,interval); //Originally global property
}​
KMcA
  • 1,155
  • 1
  • 11
  • 21
  • Please show us the non-working code. Having `movement` as a global variable outside the function should work (as long as you only animate one element) – Bergi Dec 12 '12 at 18:49
  • Never ever pass strings to [`setTimeout`](https://developer.mozilla.org/en-US/docs/DOM/window.setTimeout). Please, pass a function. – Bergi Dec 12 '12 at 18:50

1 Answers1

3

A property can never be undefined, only have a undefined as a value. In contrast, a variable may be undefined (not defined) or have undefined as a value.

When you say if (movement), in the case that movement is not defined, it will throw an exception.

When you say if (elem.movement), in teh case that elem.movement is not defined, it will evaluate to false and fail the condition without exceptions.

If you want to use movement as a global variable, you must first declare it before attempting to read from it via:

var movement;
function moveElement(elementID,final_x,final_y,interval) {
    ...
}

Alternatively, you could try to read the global movement as a property, since all global variables are just properties of the window object (in a browser):

if (window.movement) { // this will never throw an exception
    clearTimeout(movement);
}

And finally, you could switch your if statement to one that protects itself against these exceptions via the typeof operator:

if (typeof movement !== 'undefined') {
    clearTimeout(movement);
}
jbabey
  • 45,965
  • 12
  • 71
  • 94
  • I think you answered my question. I assumed without "movement" defined it would just evaluate to false. But that's where I'm wrong, it throws an exception which is why the remaining code doesn't run? Am I following your answer correctly? – KMcA Dec 12 '12 at 18:53
  • And if yes, is this just an exception that comes built into JS? – KMcA Dec 12 '12 at 19:00
  • 1
    The remaining code does not run because an exception interrupts the interpreter from continuing to parse any javascript - an unhandled exception in javascript (almost always) means the show is over. [this jsfiddle](http://jsfiddle.net/4mCUx/1/) may help clear things up. – jbabey Dec 12 '12 at 19:04
  • Exactly what I needed to fully understand. Thank you. – KMcA Dec 12 '12 at 19:10