/**
 * This is an implementation of http://www.w3.org/TR/ElementTraversal/
 * Known issues:
 *   - entity reference nodes are ignored
 *   - setting isn't treated the same way as native readonly attributes
 */

if (!Element.prototype.__lookupGetter__("firstElementChild")) {
  Element.prototype.__defineGetter__("firstElementChild", function() {
    var e = this.firstChild;
    while (e) {
      if (e.nodeType == 1)
        return e;
      e = e.nextSibling;
    }
    return null;
  });
}

if (!Element.prototype.__lookupGetter__("lastElementChild")) {
  Element.prototype.__defineGetter__("lastElementChild", function() {
    var e = this.lastChild;
    while (e) {
      if (e.nodeType == 1)
        return e;
      e = e.previousSibling;
    }
    return null;
  });
}

if (!Element.prototype.__lookupGetter__("previousElementSibling")) {
  Element.prototype.__defineGetter__("previousElementSibling", function() {
    var e = this.previousSibling;
    while (e) {
      if (e.nodeType == 1)
        return e;
      e = e.previousSibling;
    }
    return null;
  });
}

if (!Element.prototype.__lookupGetter__("nextElementSibling")) {
  Element.prototype.__defineGetter__("nextElementSibling", function() {
    var e = this.nextSibling;
    while (e) {
      if (e.nodeType == 1)
        return e;
      e = e.nextSibling;
    }
    return null;
  });
}

if (!Element.prototype.__lookupGetter__("childElementCount")) {
  Element.prototype.__defineGetter__("childElementCount", function() {
    var e = this.firstChild;
    var count = 0;
    while (e) {
      if (e.nodeType == 1)
        count++;
      e = e.nextSibling;
    }
    return count;
  });
}