if (!document.all) {

// parts taken from http://webfx.nu/dhtml/ieemu/htmlmodel.html

///////////////////////////////////////////////////////////////////////////
// MOZ2IE GLOBAL OBJECT CODE START

var moz2ie = {};

// this function adds all found attributes to their parents by code, and optionally attaches events
moz2ie.initElementAttributes = function(node) {
  if (!node) var node = document;
  var nodeList = node.selectNodes('.//@*');

  // go through all attribute-value pairs and attach them to their owner by code
  for (var i=0; i<nodeList.length; i++) {
    var theNode = nodeList[i];

    if (!theNode.ownerElement[theNode.name]) theNode.ownerElement[theNode.name] = theNode.value;

    // check if we need to attach our own events
    switch (theNode.name) {
      case "onmouseenter" :
      case "onmouseleave" :
      case "ondragstart" :
      case "ondragend" :
      case "ondrag" : {
        theNode.ownerElement.attachEvent(theNode.name, theNode.value);
        break;
      }
    }
  }
};

// capture all events on window level, and add special processing (like emulating window.event)
moz2ie.captureEvent = function(eventName) {
  eventName = eventName.substring(2);

  var eventHandler = moz2ie.event.defaultHandler;
  switch (eventName) {
    case "mouseup" :
    case "mousedown" :
    case "mousemove" :
    case "click" :
      var eventHandler = moz2ie.event[eventName + "Handler"];
  };
  window.addEventListener(eventName, eventHandler, true);
};

// this object provides ie's global window.event emulation and adds drag events
moz2ie.event = {};
moz2ie.event.useDragElement = false;
moz2ie.event.dragging = false;
moz2ie.event.dragElement = null;
moz2ie.event.defaultHandler = function(evt) {
  window.event = evt;
};
moz2ie.event.mousedownHandler = function(evt) {
  moz2ie.event.dragElement = evt.target;
  window.event = evt;
};
moz2ie.event.mouseupHandler = function(evt) {
  window.event = evt;

  // in case we were dragging an element, fire all dragend handlers
  if (moz2ie.event.dragging) {
    moz2ie.event.useDragElement = true;
    for (var handler in moz2ie.event.dragElement.dragendHandlers) eval(handler);

    // restore
    moz2ie.event.useDragElement = false;

    // we do NOT set dragging to false.
    // moz fires a click event after this mouseup, which is cancelled to be IE compatible
    // therefore we have a special clickHandler which checks for dragging=true
  }
  moz2ie.event.dragElement = null;
};
moz2ie.event.mousemoveHandler = function(evt) {
  window.event = evt;
  if (moz2ie.event.dragElement) {

    // for both dragstart or drag handlers, make srcElement use our dragElement
    moz2ie.event.useDragElement = true;

    // if we weren't dragging before, it's a dragstart
    if (!moz2ie.event.dragging) {
      moz2ie.event.dragging = true;
      for (var handler in moz2ie.event.dragElement.dragstartHandlers) eval(handler);
    }

    // now it's a drag event so call its drag handlers
    for (var handler in moz2ie.event.dragElement.dragHandlers) eval(handler);

    // restore to mousemove
    moz2ie.event.useDragElement = false;
  }
};
moz2ie.event.clickHandler = function(evt) {
  window.event = evt;
  if (moz2ie.event.dragging) {
    // cancel the click event after a dragEnd
    moz2ie.event.dragging = false;
    window.event.cancelBubble = true;
  }
};

// MOZ2IE GLOBAL OBJECT CODE END
///////////////////////////////////////////////////////////////////////////


Node.prototype.replaceNode = function(otherNode)
{
  this.parentNode.replaceChild(otherNode, this);
};

Node.prototype.swapNode = function(otherNode)
{
  var nextSibling = this.nextSibling;
  var parentNode = this.parentNode;
  this.parentNode.replaceChild(this, otherNode);
  parentNode.insertBefore(otherNode, nextSibling);
};

Text.prototype.__defineGetter__("parentElement", function () {
  return this.parentNode;
});

HTMLElement.prototype.__defineGetter__("parentElement", function () {
  return this.parentNode;
});

// attatchEvent and detachEvent for elements, document and window, including drag implementation code
HTMLElement.prototype.attachEvent = function(eventName, methodName)
{
    eventName = eventName.substring(2);

  switch (eventName) {
    case "mouseenter":
      this.attachEvent("onmouseover", methodName);
      break;
    case "mouseleave":
      this.attachEvent("onmouseout", methodName);
      break;
    case "dragstart" :
    case "dragend" :
    case "drag" : {
      // TODOE: fix dat ie de handler plaatst op basis van iets anders dan zn eigen functie
      if (!this[eventName + 'Handlers']) this[eventName + 'Handlers'] = {};
      if (!this[eventName + 'Handlers'][methodName]) this[eventName + 'Handlers'][methodName] = methodName;
      break;
    }
    default: {
      methodName._q42_EventHandler = function (evt) { return methodName(evt); };
      this.addEventListener(eventName, methodName._q42_EventHandler, false);
    }
  }
};

HTMLElement.prototype.detachEvent = function(eventName, methodName)
{
    eventName = eventName.substring(2);
  switch (eventName) {
    case "mouseenter":
      this.detachEvent("onmouseover", methodName);
      break;
    case "mouseleave":
      this.detachEvent("onmouseout", methodName);
      break;
    case "dragstart" :
    case "dragend" :
    case "drag" : {
      if (this[eventName + 'Handlers'][methodName]) delete this[eventName + 'Handlers'][methodName];
      if (this[eventName + 'Handlers'].length == 0) delete this[eventName + 'Handlers'];
      break;
    }
    default: {
       if (typeof(methodName._q42_EventHandler) == "function")
        this.removeEventListener(eventName, methodName._q42_EventHandler, false);
       else
        this.removeEventListener(eventName, methodName, true);
    }
  }
};

window.attachEvent = HTMLElement.prototype.attachEvent;
window.detachEvent = HTMLElement.prototype.detachEvent;
HTMLDocument.prototype.attachEvent = HTMLElement.prototype.attachEvent;
HTMLDocument.prototype.detachEvent = HTMLElement.prototype.detachEvent;

// do required things onload
window.attachEvent("onload", function(evt) {
  moz2ie.captureEvent("onmousemove");
  moz2ie.captureEvent("onmousedown");
  moz2ie.captureEvent("onmouseover");
  moz2ie.captureEvent("onmouseout");
  moz2ie.captureEvent("onmouseup");
  moz2ie.captureEvent("onclick");
  moz2ie.captureEvent("ondblclick");
  moz2ie.captureEvent("onkeypress");
  moz2ie.captureEvent("onkeyup");
  moz2ie.captureEvent("onkeydown");
  moz2ie.captureEvent("onfocus");
  moz2ie.captureEvent("onblur");
  moz2ie.captureEvent("onresize");
  moz2ie.captureEvent("onchange");
  moz2ie.captureEvent("oncontextmenu");

  moz2ie.initElementAttributes();
  window.document.readyState = 'complete';

  // this reInits all element attributes and events when html is changed (by adding nodes or setting innerHTML)
  document.body.addEventListener("DOMNodeInserted", function(evt) {
    var node = evt.target;
    while (node.nodeType != 1) node = node.parentNode;
    window.moz2ie.initElementAttributes(node)
  }, false);
});

// document.frames returns the iframe collection
HTMLDocument.prototype.__defineGetter__("frames", function () {
  return this.getElementsByTagName("iframe");
});

// document.frames returns the iframe collection
HTMLBodyElement.prototype.focus = function () {
  window.focus();
};

// Modify Mozilla's Event object
// TODO: fix the dataTransfer properties to reflect correct values
Event.prototype.dataTransfer = {
  "dropEffect" : "none",
  "effectAllowed" : "all"
};
Event.prototype.__defineGetter__("x", function () {
  return this.clientX;
});
Event.prototype.__defineGetter__("y", function () {
  return this.clientY;
});
Event.prototype.__defineGetter__("srcElement", function () {
  // if specified to do so, return the dragged element
  if (window.moz2ie.event.useDragElement) return window.moz2ie.event.dragElement;

  // otherwise return evt.target
  var node = this.target;
    //while (node.nodeType != 1) node = node.parentNode;

  return node;
});
Event.prototype.__defineSetter__("cancelBubble", function (b) {
   if (b) this.stopPropagation();
});
Event.prototype.__defineSetter__("returnValue", function (b) {
   if (!b) this.preventDefault();
});
Event.prototype.__defineGetter__("offsetX", function () {
   return this.layerX;
});
Event.prototype.__defineGetter__("offsetY", function () {
   return this.layerY;
});
Event.prototype.__defineGetter__("fromElement", function () {
   var node;
   if (this.type == "mouseover")
      node = this.relatedTarget;
   else if (this.type == "mouseout")
      node = this.target;
   else
      return null;
   var node = this.target;
   while (node.nodeType != 1) node = node.parentNode;
   return node;
});
Event.prototype.__defineGetter__("toElement", function () {
   var node;
   if (this.type == "mouseout")
      node = this.relatedTarget;
   else if (this.type == "mouseover")
      node = this.target;
   else
      return null;
   var node = this.target;
   while (node.nodeType != 1) node = node.parentNode;
   return node;
});

/**
 * Add IE specific DHTML support.
 */
HTMLElement.prototype.getBoundingClientRect = function()
{
  var box = document.getBoxObjectFor(this);
  return { left:box.x, top:box.y, right:box.x + box.width, bottom:box.y + box.height };
};

Node.prototype.selectNodes = function(xpath)
{
  var xpe = new XPathEvaluator();
  var it;
  try
  {
    it = xpe.evaluate(xpath, this, xpe.createNSResolver(this), null, null);
  }
  catch (e)
  {
    alert("Node.prototype.selectNodes('" + xpath + "')\ntrace:\n" + this.pathTrace + "\nxml:" + this.qxml());
  }

  var list = [], node;
  while (node = it.iterateNext())
  {
    if (!node.selectNodes)
    {
      var base;
      switch (node.nodeType)
      {
        case 1:
          base = Element;
          break;
        case 2:
          base = Attr;
          break;
        case 3:
          base = Text;
          break;
        case 4:
          base = CDataSection;
          break;
        default:
          alert("Node.prototype.selectNodes unknown node type");
          return null;
      }

      for (var prop in base.prototype)
      {
        try {
          node[prop] = base.prototype[prop];
        } catch(e) {}
      }
    }

    if (node && node != this)
      node.pathTrace = (this.pathTrace ? this.pathTrace + "\n" : "") + "selectNodes('" + xpath + "')";

    list.push(node);
  }

  return list;
};

// document.all[] or element.all[]
Node.prototype.__defineGetter__("all", function()
{
  var result = {};
  var nodeList = this.selectNodes('.//*[@id!=""]');
  for (var i=0; i<nodeList.length; i++) {
  var theNode = nodeList[i];
  var id = theNode.getAttribute("id");
  if (!result[id]) result[id] = theNode;
  }
  return result;
});

// ActiveXObject
ActiveXObject = function(objName)
{
  switch(objName.toLowerCase()) {
    case "microsoft.xmldom":
      return document.implementation.createDocument("text/xml", "", null);
    case "microsoft.xmlhttp":
      return XMLHttpRequest();
    default :
      alert("Not implemented: new ActiveXObject(\"" + objName + "\")");
  }
};

XMLDocument.prototype.loadXML = function(xmlString)
{
  var childNodes = this.childNodes;
  for (var i = childNodes.length - 1; i >= 0; i--)
    this.removeChild(childNodes[i]);

  var dp = new DOMParser();
  var newDOM = dp.parseFromString(xmlString, "text/xml");
  var newElt = this.importNode(newDOM.documentElement, true);
  this.appendChild(newElt);
};

Node.prototype.selectSingleNode = function(xpath)
{
  var xpe = new XPathEvaluator();
  var result;
  try
  {
    result = xpe.evaluate(xpath, this, xpe.createNSResolver(this), XPathResult.FIRST_ORDERED_NODE_TYPE, null);
  }
  catch (e)
  {
    alert("Node.prototype.selectSingleNode('" + xpath + "')\ntrace:\n" + this.pathTrace + "\nxml:" + this.qxml());
  }

  var node = result.singleNodeValue;

  if (node && node != this)
    node.pathTrace = (this.pathTrace ? this.pathTrace + "\n" : "") + "selectSingleNode('" + xpath + "')";

  return node;
};

}
