/**
  Various functions that may be browser-dependent.
*/

/**
  Cancel bubbling of the given event. In IE the event
  seems to be accessible only from the Window object.
  In Firefox it's passed as an argument to the handler.
  Therefore we test to see if the passed event exists,
  and if it doesn't, we use the global event
  object.
*/
function BrowserCancelBubble(event, preventDefault)
{
  var e = BrowserGetEvent(event);
  if (e == null)
    return;
    
  e.returnValue = false;
    
  e.cancelBubble = true;
  if (e.stopPropagation !== undefined)
    e.stopPropagation();
    
  if ((preventDefault) && (e.preventDefault))
    e.preventDefault();
}

/** 
  Passes back the browser's event object.
  It tries to standardise the structure of the
  event object too.
*/
function BrowserGetEvent(event)
{
  var e = event;
  if (e === undefined)
    e = window.event;

  if (e == null)
    return;

  //Standardise if it's a keypress even
  if (e.keyCode === undefined && e.which != null)
    e.keyCode = e.which;

  return e;
}

/**
  Returns the object on which the event occurred.
  You should call BrowserGetEvent() before calling
  this method. This is tested and working in IE6,
  Safari and Firefox.
*/
function BrowserGetTarget(event)
{
  var target = event.srcElement;
  if (target == null)
    target = (event.target.tagName ? event.target : event.target.parentNode);
  return target;
}

/**
  Get a copy of XMLHttpRequest for the platform.
*/
function BrowserGetXMLHttpRequest()
{
  if (window.XMLHttpRequest)
    return new XMLHttpRequest();

  if (window.ActiveXObject)
    return new ActiveXObject("Microsoft.XMLHTTP");
    
  alert("This browser does not support XMLHttpRequest");
  
  return null;
}

/**
  Make a deep copy of the oldNode, where every node is imported
  into the given document. The original nodes aren't changed,
  and while the new nodes are owned by the document, they are
  not added to it.
  
  Returns a new node, identical to oldNode but owned by document.
*/
function BrowserImportNode(document, oldNode)
{
  // Safari
  if (navigator.userAgent.indexOf("KHTML") != -1)
    return SafariImportHtml(oldNode);
  
  // Mozilla
  if (document.importNode)
    return document.importNode(oldNode, true);
    
  var ieVersion = getInternetExplorerVersion();
  if (ieVersion >= 8.0)
  {
    return IE8ImportChild(oldNode, null);
  }

  // IE6
  return IE6ImportChild(oldNode, null);
}

function IE8ImportChild(node)
{
  
  var attrList = node.attributes;
  var attrCount = attrList.length;
  
  // In IE8, you can't just set the attributes using the DOM because
  // IE won't understand them. The only workaround appears to be to
  // create a string representation of the HTML, and then pass
  // that to createElement!! You really have to wonder why they
  // even bothered to implement the DOM in the first place.
  var attrString = "<" + node.tagName;
  for (var attrIndex = 0; attrIndex < attrCount; attrIndex++)
  {
    var attr = attrList[attrIndex];
    var attrValue = attr.value.replace(/"/g, "\\\"");
    attrString = attrString + " " + attr.name + "=\"" + attrValue + "\"";
  }
  attrString = attrString + ">";
  
  var newElement = document.createElement(attrString);
  
  var nextChild = node.firstChild;
  while (nextChild != null)
  {
    var nodeType = nextChild.nodeType;
    if (nodeType == 1)
    {          // Element node
      newElement.appendChild(IE8ImportChild(nextChild))
    }
    else if (nodeType == 3)     // Text node
    {
      newElement.innerText = nextChild.text;
    }
    else
      alert("Got unexpected node type: " + nodeType);
      
    nextChild = nextChild.nextSibling;
  }
  
  return newElement;
}

function getInternetExplorerVersion() 
{
    var rv = -1; // Return value assumes failure.
    if (navigator.appName == 'Microsoft Internet Explorer') {
        var ua = navigator.userAgent;
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null)
            rv = parseFloat(RegExp.$1);
    }
    return rv;
}


/**
  Deep copy the XML document and turn it into HTML nodes.
  This seems to be necessary to get around bugs (?) in Safari's
  rendering engine, which appears to enter into a mode where
  it can't work out what's going on. I duplicated this behaviour
  by getting Safari to work perfectly, then quit Safari and
  restarted it -- after which it no longer worked.
*/
function SafariImportHtml(node)
{
  var newElement = document.createElement(node.tagName);
  var attrList = node.attributes;
  var attrCount = attrList.length;
  
  for (var attrIndex = 0; attrIndex < attrCount; attrIndex++)
  {
    var attr = attrList[attrIndex];
    if (attr.name != "xmlns")
      newElement.setAttribute(attr.name, attr.value);
  }
  
  var nextChild = node.firstChild;
  while (nextChild != null)
  {
    var nodeType = nextChild.nodeType;
    if (nodeType == 1)          // Element node
      newElement.appendChild(SafariImportHtml(nextChild))
    else if (nodeType == 3)     // Text node
    {
      var textNode = document.createTextNode(nextChild.nodeValue);
      newElement.appendChild(textNode);
    }
    else
      alert("Got unexpected node type: " + nodeType);
      
    nextChild = nextChild.nextSibling;
  }
  
  return newElement;
}

/**
  This is required to perform a deep import of nodes
  in IE6. The code is not used in Mozilla/Safari, because
  they support importNode. The code is required because MS
  did not implement the DOM properly, presumably because
  the IE6 developers or team leaders are lame idiots.
*/
function IE6ImportChild(node)
{
  var attrList = node.attributes;
  var attrCount = attrList.length;
  
  // In IE6, you can't just set the attributes using the DOM because
  // IE won't understand them. The only workaround appears to be to
  // create a string representation of the HTML, and then pass
  // that to createElement!! You really have to wonder why they
  // even bothered to implement the DOM in the first place.
  var attrString = "<" + node.tagName;
  for (var attrIndex = 0; attrIndex < attrCount; attrIndex++)
  {
    var attr = attrList[attrIndex];
    var attrValue = attr.value.replace(/"/g, "\\\"");
    attrString = attrString + " " + attr.name + "=\"" + attrValue + "\"";
  }
  attrString = attrString + ">";
  
  var newElement = document.createElement(attrString);
  
  var nextChild = node.firstChild;
  while (nextChild != null)
  {
    var nodeType = nextChild.nodeType;
    if (nodeType == 1)          // Element node
      newElement.appendChild(IE6ImportChild(nextChild))
    else if (nodeType == 3)     // Text node
    {
      var textNode = document.createTextNode(nextChild.text);
      newElement.appendChild(textNode);
    }
    else
      alert("Got unexpected node type: " + nodeType);
      
    nextChild = nextChild.nextSibling;
  }
  
  return newElement;
}

/**
  Find the first element node that's a child of the given node.
*/
function BrowserGetFirstElement(fromNode)
{
  var nextNode = fromNode.firstChild;
  while (nextNode != null)
  {
    if (nextNode.nodeType == 1)
      break;
    nextNode = nextNode.nextSibling;
  }
  
  return nextNode;
}

function BrowserIsSafari()
{
  return navigator.userAgent.indexOf("Safari") != -1;
}

//
// Do any cleanup needed by browsers after the page
// has been fully emitted.
//
function BrowserCleanup()
{
  BrowserFixImages();
}

function BrowserLayoutChanged()
{
  BrowserFixImages();
}

//
// Apply MSIE transparency filter to IMG elements.
// This is to work around yet another bug in IE6.
//
function BrowserFixImages()
{
  if (navigator.vendor != undefined)
    return;
    
  var images = document.images;
  for (var index = 0; index < images.length; index++)
  {
    var element = images[index];
    if (element.fixed != null)
      continue;
    
    var width = element.scrollWidth;

    // The width is 0 if the image is hidden, eg, contained
    // in an invisible DIV. In this case we need to wait until
    // the parent is fixed. Unfortauntely there does not seem to
    // be an event to do this, so we hard-code calls to
    // BrowserLayoutChange which will call this method again.
    if (width == 0)
      continue;

    var src = element.getAttribute("src");
    var height = element.scrollHeight;
    element.fixed = true;
    element.src = "/tang/bug.gif";
    element.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "')";
    element.style.width = width + "px";
    element.style.height = height + "px";
  }
}
