Object.extend(Element, {
  setText: function(element, text) {
    element = $(element);
    Element.removeChildNodes(element);
    element.appendChild(document.createTextNode(text));
  },

  removeChildNodes: function(element) {
    element = $(element);
    while (element.childNodes.length) {
      element.removeChild(element.childNodes[0]);
    }
  }
});

var CancellablePeriodicalExecuter = Class.create();
CancellablePeriodicalExecuter.prototype =
{
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;
    this.interval = false;

    this.registerCallback();
  },

  registerCallback: function() {
    if (this.interval === false) {
      this.interval = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
    }
  },

  cancelCallback: function() {
    if (this.interval !== false) {
      clearInterval(this.interval);
      this.interval = false;
    }
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
