O3Global.DOM = new function()
{
  // Get something by its ID (cross browser compat)
  function getById(id)
  {
    // IE
    if (document.all)
    {
      return document.all[id];
    }
    // Netscape
    else if(document.layers)
    {
      return document.layers[id];
    }
    // DOM - eg Opera
    else if(document.getElementById)
    {
      var hElement = document.getElementById(id);

      // Firefox, check for elements by name (no merged name/id spaces)
      if(hElement == null)
      {
        if(document.getElementsByName && document.getElementsByName(id) && document.getElementsByName(id)[0])
        {
          // Build array for more elements (radio boxes)
          hElement = document.getElementsByName(id);
          if(hElement.length == 1)
            hElement = hElement[0];
        }
      }

      // Firefox, check subforms if needed
      if(hElement == null)
      {
        for(var sForm in document.forms)
        {
          var hForm = document.forms[sForm];
          if(hForm.elements && hForm.elements[id])
          {
            hElement = hForm.elements[id];
            break;
          }
        }
      }

      return hElement;
    }
    // Not supported
    else
    {
      return null;
    }
  }

  // Clear a div
  function clearDiv(sDiv)
  {
    var oPane = getById(sDiv);
    if(!oPane)
      return;

    // Clear load data if present
    if(O3Global.Ajax)
      O3Global.Ajax.clearEntry(sDiv);

    oPane.innerHTML = '';
  }

  function showDiv(sDiv)
  {
    var oDiv = getById(sDiv);
    if(oDiv && oDiv.style)
      oDiv.style.display = '';
  }

  function hideDiv(sDiv)
  {
    var oDiv = getById(sDiv);
    if(oDiv && oDiv.style)
      oDiv.style.display = 'none';
  }

  function removeDiv(sDiv)
  {
    var oDiv = getById(sDiv);
    if(oDiv && oDiv.parentElement)
      oDiv.parentElement.removeChild(oDiv);
  }

  function getAbsoluteLeft(oElement)
  {
    var iLeft = oElement.offsetLeft;
    while(oElement.offsetParent != null)
    {
      oElement = oElement.offsetParent;
      iLeft   += oElement.offsetLeft;
    }

    return iLeft;
  }

  function getAbsoluteTop(oElement)
  {
    var iTop = oElement.offsetTop;
    while(oElement.offsetParent != null)
    {
      oElement = oElement.offsetParent;
      iTop    += oElement.offsetTop;
    }

    return iTop;
  }

  function setImageOpacity(sId, fOpacity)
  {
    // Get image
    var hImage = getById(sId);
    if(!hImage)
      return;

    // Set opacity styles
    if(hImage.filters && hImage.filters.alpha)
      hImage.filters.alpha.opacity = fOpacity * 100;
    else
    {
      hImage.style.KHTMLOpacity = fOpacity;
      hImage.style.MozOpacity   = fOpacity;
      hImage.style.opacity      = fOpacity;
    }
  }

  function insertRow(sTable, aColumns, sBefore, sId)
  {
    // Fetch table body
    var oTable = getById(sTable);
    if(!oTable)
      return false;

    var oTBody = oTable.getElementsByTagName('tbody')[0];
    if(!oTBody)
    {
      // Create body (first time insert)
      oTBody = document.createElement('tbody');
      oTable.appendChild(oTBody);
    }

    // Create new row
    var oRow = document.createElement('tr');
    if(sId)
      oRow.id = sId;

    // Create columns & add them
    for(var i = 0; i < aColumns.length; i++)
    {
      var oColumn = document.createElement('td');
      oColumn.innerHTML = aColumns[i];
      oRow.appendChild(oColumn);
    }

    // Check for before row
    var oBefore = null;
    if(sBefore)
      oBefore = getById(sBefore);

    // Insert
    if(oBefore)
      oTBody.insertBefore(oRow, oBefore);
    else
      oTBody.appendChild(oRow);

    return true;
  }

  function removeRow(sTable, sRow)
  {
    // Fetch table body
    var oTable = getById(sTable);
    if(!oTable)
      return false;

    var oTBody = oTable.getElementsByTagName('tbody')[0];
    if(!oTBody)
      return false;

    // Find row
    var oRow = getById(sRow);
    if(!oRow)
      return false;

    // Remove row
    oTBody.removeChild(oRow);

    return true;
  }

  function getStyle(oElement, sProp)
  {
    if(oElement.currentStyle)
      return oElement.currentStyle[sProp];
    else if(window.getComputedStyle)
      return document.defaultView.getComputedStyle(oElement, null).getPropertyValue(sProp);

    return null;
  }

  function zoomImage(sImage, fZoom)
  {
    // Fetch image
    var img = getById(sImage);
    if(!img)
      return false;

    // Decide original size
    var imgSize = new Image();
    imgSize.src = img.src;

    // Apply new sizes
    img.width  = Math.round(imgSize.width  * fZoom);
    img.height = Math.round(imgSize.height * fZoom);

    return true;
  }

  function scrollHorizontal(oDiv, iScroll)
  {
    if(!oDiv)
      return;

    var iPosX = oDiv.scrollLeft - iScroll;
    if(iPosX < 0)
      iPosX = 0;
    else if(iPosX > oDiv.scrollWidth)
      iPosX = oDiv.scrollWidth;

    oDiv.scrollLeft = iPosX;
  }

  function scrollVertical(oDiv, iScroll)
  {
    if(!oDiv)
      return;

    var iPosY = oDiv.scrollTop - iScroll;
    if(iPosY < 0)
      iPosY = 0;
    if(iPosY > oDiv.scrollHeight)
      iPosY = oDiv.scrollHeight;

    oDiv.scrollTop = iPosY;
  }

  function setClass(sItem, sClass)
  {
    var oItem = getById(sItem);
    if(oItem)
      oItem.className = sClass;
  }

  // Bind public functions
  this.getById          = getById;
  this.clearDiv         = clearDiv;
  this.showDiv          = showDiv;
  this.hideDiv          = hideDiv;
  this.removeDiv        = removeDiv;
  this.getAbsoluteLeft  = getAbsoluteLeft;
  this.getAbsoluteTop   = getAbsoluteTop;
  this.insertRow        = insertRow;
  this.removeRow        = removeRow;
  this.getStyle         = getStyle;
  this.zoomImage        = zoomImage;
  this.scrollHorizontal = scrollHorizontal;
  this.scrollVertical   = scrollVertical;
  this.setClass         = setClass;
  this.setImageOpacity  = setImageOpacity;
}