/**
 * layers.js
 *
 * This javascript file contains a series of utility methods that manipulate layers.
 * These methods are designed to remove the burden of ensuring browser compatibility
 * from the application designer.
 *
 * Copyright Brian W. Drake, DigitalGlobe, Inc, 2002
 * bdrake@digitalglobe.com
 *
 * Based on the work of:
 *   - Mike Hall, Dynamic Drive, 1999
 *   - Mike Deardorff, DigitalGlobe Inc, 2002
 *
 * Browsers Supported:  IE5.0, IE5.5, IE6.0, NS4.7x, NS6, NS7, Mozilla0.9, Mozilla1.0
 *
 * Dependencies:  Depends on browser.js.  Include browser.js in your jsp or html prior
 *   to including this file.
 *
 * Browser Compatibility:
 *   - No known problems at this time (for the supported browsers)
 */



// -----------------------------------------------------------------------------
// Layer Creation
// -----------------------------------------------------------------------------

// Create a DHTML layer with the specified name
function createLayer(name, left, top, width, height, visible, content)
{
  var layer;

  if (browser.isOldNS)
  {
    document.writeln('<layer name="' + name + '" left=' + left + ' top=' + top + ' width=' + width + ' height=' + height +  ' visibility=' + (visible ? '"show"' : '"hide"') +  '>');
    document.writeln(content);
    document.writeln('</layer>');
    layer = getLayer(name);
    layer.width = width;
    layer.height = height;
  }
  else
  {
    document.writeln('<div id="' + name + '" style="position:absolute; overflow:none; left:' + left + 'px; top:' + top + 'px; width:' + width + 'px; height:' + height + 'px;' + ' visibility:' + (visible ? 'visible;' : 'hidden;') +  '">');
    document.writeln(content);
    document.writeln('</div>');
  }
}




// -----------------------------------------------------------------------------
// Layer Access
// -----------------------------------------------------------------------------

// Return a reference to the named layer.  Null if the layer cannot be found.
function getLayer(name)
{
  var layer = null;

  if (browser.isOldNS)
    layer = findLayer(name, document);
  if (browser.isOldIE)
    layer = eval('document.all.' + name);
  if (browser.isDOM)
    layer = document.getElementById(name);

  return layer;
}


// This method is specifically for old NS versions that have the document.layers
//   structure.  It will look for the named layer in the specified document, and
//   if there are layers in the layers, it will search those recursively.
function findLayer(name, doc)
{
  var i, layer;

  for (i = 0; i < doc.layers.length; i++)
  {
    layer = doc.layers[i];
    if (layer.name == name)
      return layer;
    if (layer.document.layers.length > 0)
    {
      layer = findLayer(name, layer.document);
      if (layer != null)
        return layer;
    }
  }

  return null;
}





// ----------------------------------------------------------------------------
// Layer content
// ----------------------------------------------------------------------------

// Set or replace the content of a layer
function setLayerContent(layerName, content)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
  {
    layer.document.open();
    layer.document.writeln(content);
    layer.document.close();
  }
  if (browser.isOldIE || browser.isDOM)
  {
    layer.innerHTML = content;
  }
}


// Set the cursor for the given layer.  Some cursors include "wait", "crosshair", "move",
//   "normal"
function setLayerCursor(layerName, cursorName)
{
  var layer = getLayer(layerName);

  layer.style.cursor = cursorName;
}




//-----------------------------------------------------------------------------
// Layer visibility.
//-----------------------------------------------------------------------------

// Hide the specified layer
function hideLayer(layerName)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.visibility = "hide";
  if (browser.isOldIE || browser.isDOM)
    layer.style.visibility = "hidden";
}


// Show the specified layer
function showLayer(layerName)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.visibility = "show";
  if (browser.isOldIE || browser.isDOM)
    layer.style.visibility = "visible";
}


// Cause the specified layer to inherit the visibility from its parent.
function inheritLayer(layerName)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.visibility = "inherit";
  if (browser.isOldIE || browser.isDOM)
    layer.style.visibility = "inherit";
}


// Returns "visible" if the layer is presently visible, or "hidden" if it is hidden
function getVisibility(layerName)
{
  var layer = getLayer(layerName);
  var visStatus = "visible";

  if (browser.isOldNS)
  {
    if (layer.visibility == "show")
      visStatus = "visible";
    if (layer.visibility == "hide")
      visStatus = "hidden";
  }
  if (browser.isOldIE || browser.isDOM)
    visStatus = layer.style.visibility;

  return visStatus;
}


// Returns "true" if the specified layer is visible; false otherwise
function isVisible(layerName)
{
  return (getVisibility(layerName) == "visible");
}





//-----------------------------------------------------------------------------
// Layer background.
//-----------------------------------------------------------------------------

// Sets the background color of the specified layer
function setLayerBGColor(layerName, color)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.bgColor = color;
  if (browser.isOldIE || browser.isDOM)
    layer.style.backgroundColor = color;
}


// Sets a background image for the specified layer
function setLayerBGImage(layerName, src)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.background.src = src;
  if (browser.isOldIE || browser.isDOM)
    layer.style.backgroundImage = "url(" + src + ")";
}






//-----------------------------------------------------------------------------
// Layer positioning.
//-----------------------------------------------------------------------------


// Moves the layer to the positions specified by x, y
function moveLayerTo(layerName, x, y)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.moveTo(x, y);
  if (browser.isOldIE || browser.isDOM)
  {
    layer.style.left = x;
    layer.style.top  = y;
  }
}


// Moves the layer by a delta X and a delta Y
function moveLayerBy(layerName, dx, dy)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.moveBy(dx, dy);
  if (browser.isOldIE || browser.isDOM)
  {
    layer.style.left = parseInt(layer.style.left)+dx;
    layer.style.top = parseInt(layer.style.top)+dy;
  }
}


// Gets the X position of the left border of the layer
function getLayerLeft(layerName)
{
  var layer = getLayer(layerName);
  var left = -1;

  if (browser.isOldNS)
    left = layer.left;
  if (browser.isOldIE || browser.isDOM)
    left = parseInt(layer.style.left);

  return(left);
}


// Returns the Y coordinate of the top of the layer
function getLayerTop(layerName)
{
  var layer = getLayer(layerName);
  var top = -1;

  if (browser.isOldNS)
    top = layer.top;
  if (browser.isOldIE || browser.isDOM)
    top = parseInt(layer.style.top);

  return(top);
}


// Returns the X coordinate of the right-hand border of the layer
function getLayerRight(layerName)
{
  var layer = getLayer(layerName);
  var right = -1;

  if (browser.isOldNS)
    right = layer.left + getLayerWidth(layerName);
  if (browser.isOldIE || browser.isDOM)
    right = parseInt(layer.style.left) + getLayerWidth(layerName);

  return(right);
}


// Returns the Y coordinate of the bottom of the layer
function getLayerBottom(layerName)
{
  var layer = getLayer(layerName);
  var bottom = -1;

  if (browser.isOldNS)
    bottom = layer.top + getLayerHeight(layerName);
  else if (browser.isOldIE || browser.isDOM)
    bottom = parseInt(layer.style.top) + getLayerHeight(layerName);

  return(bottom);
}


// Returns the upper left X coordinate relative to the parent layer
function getLayerPageLeft(layerName)
{
  var layer = getLayer(layerName);
  var pageLeft = -1;

  if (browser.isOldNS)
    pageLeft = layer.pageX;
  if (browser.isOldIE || browser.isDOM)
    pageLeft = layer.offsetLeft;

  return(pageLeft);
}


// Returns the upper left Y coordinate relative to the parent layer
function getLayerPageTop(layerName)
{
  var layer = getLayer(layerName);
  var pageTop = -1;

  if (browser.isOldNS)
    pageTop = layer.pageY;
  if (browser.isOldIE || browser.isDOM)
    pageTop = layer.offsetTop;

  return(pageTop);
}


// Returns the width of the specified layer
function getLayerWidth(layerName)
{
  var layer = getLayer(layerName);
  var width = -1;

  if (browser.isOldNS)
  {
    if (layer.document.width)
      width = layer.document.width;
    else
      width = layer.clip.right - layer.clip.left;
  }
  if (browser.isOldIE || browser.isDOM)
  {
    if (layer.style.width)
      width = parseInt(layer.style.width);
    else
      width = parseInt(layer.offsetWidth);
  }

  return(width);
}


// Returns the height of the layer
function getLayerHeight(layerName)
{
  var layer = getLayer(layerName);
  var height = -1;

  if (browser.isOldNS)
  {
    if (layer.document.height)
      height = layer.document.height;
    else
      height = layer.clip.bottom - layer.clip.top;
  }
  if (browser.isOldIE || browser.isDOM)
  {
    if (false && layer.style.height)
      height = parseInt(layer.style.height);
    else
      height = parseInt(layer.offsetHeight);
  }

  return(height);
}


// Returns the z-index of the specified layer
function getLayerZIndex(layerName)
{
  var layer = getLayer(layerName);
  var index = -1;

  if (browser.isOldNS)
    index = layer.zIndex;
  if (browser.isOldIE || browser.isDOM)
    index = layer.style.zIndex;

  return(index);
}


// Sets the Z-index of the specified layer
function setLayerZIndex(layerName, z)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
    layer.zIndex = z;
  if (browser.isOldIE || browser.isDOM)
    layer.style.zIndex = z;
}






//-----------------------------------------------------------------------------
// Layer clipping.
//-----------------------------------------------------------------------------

// Clips a layer (that is, sets the visible area) according to the given coordinates/dimensions
function clipLayer(layerName, clipleft, cliptop, clipright, clipbottom)
{
  var layer = getLayer(layerName);

  if (browser.isOldNS)
  {
    layer.clip.left   = clipleft;
    layer.clip.top    = cliptop;
    layer.clip.right  = clipright;
    layer.clip.bottom = clipbottom;
  }
  if (browser.isOldIE || browser.isDOM)
    layer.style.clip = 'rect(' + cliptop + ' ' +  clipright + ' ' + clipbottom + ' ' + clipleft +')';
}


// Gets the X coordinate of the left of the clipped (visible) part of the layer
function getLayerClipLeft(layerName)
{
  var layer = getLayer(layerName);
  var cLeft = -1;

  if (browser.isOldNS)
    cLeft = layer.clip.left;
  if (browser.isOldIE || browser.isDOM)
  {
    var str = layer.style.clip;
    if (!str)
      cLeft = 0;
    else
    {
      var clip = getIELayerClipValues(layer.style.clip);
      cLeft = clip[3];
    }
  }

  return(cLeft);
}


// Gets the Y coordinate of the top of the clipped (visible) part of the layer
function getLayerClipTop(layerName)
{
  var layer = getLayer(layerName);
  var cTop = -1;

  if (browser.isOldNS)
    cTop = layer.clip.top;
  if (browser.isOldIE || browser.isDOM)
  {
    var str =  layer.style.clip;
    if (!str)
      cTop = 0;
    else
    {
      var clip = getIELayerClipValues(layer.style.clip);
      cTop = clip[0];
    }
  }

  return(cTop);
}


// Gets the X coordinate of the right of the clipped (visible) part of the layer
function getLayerClipRight(layerName)
{
  var layer = getLayer(layerName);
  var cRight = -1;

  if (browser.isOldNS)
    cRight = layer.clip.right;
  if (browser.isOldIE || browser.isDOM)
  {
    var str = layer.style.clip;
    if (!str)
      cRight = getLayerWidth(layerName);
    else
    {
      var clip = getIELayerClipValues(layer.style.clip);
      cRight = clip[1];
    }
  }

  return(cRight);
}


// Gets the Y coordinate of the bottom of the clipped (visible) part of the layer
function getLayerClipBottom(layerName)
{
  var layer = getLayer(layerName);
  var cBottom = -1;

  if (browser.isOldNS)
    cBottom = layer.clip.bottom;
  if (browser.isOldIE || browser.isDOM)
  {
    var str = layer.style.clip;
    if (!str)
      cBottom = getLayerHeight(layerName);
    else
    {
      var clip = getIELayerClipValues(layer.style.clip);
      cBottom = clip[2];
    }
  }

  return(cBottom);
}


// Gets the height of the clipped (visible) part of the layer
function getLayerClipWidth(layerName)
{
  var layer = getLayer(layerName);
  var cWidth = -1;

  if (browser.isOldNS)
    cWidth = layer.clip.width;
  if (browser.isOldIE || browser.isDOM)
  {
    var str = layer.style.clip;
    if (!str)
      cWidth = getLayerWidth(layerName);
    else
    {
      var clip = getIELayerClipValues(layer.style.clip);
      cWidth = (clip[1] - clip[3]);
    }
  }

  return(cWidth);
}


// Gets the height of the clipped (visible) part of the layer
function getLayerClipHeight(layerName)
{
  var layer = getLayer(layerName);
  var cHeight = -1;

  if (browser.isOldNS)
    cHeight = layer.clip.height;
  if (browser.isOldIE || browser.isDOM)
  {
    var str =  layer.style.clip;
    if (!str)
      cHeight = getLayerHeight(layerName);
    else
    {
      var clip = getIELayerClipValues(layer.style.clip);
      cHeight = (clip[2] - clip[0]);
    }
  }

  return(cHeight);
}


// Parses clip values specific to the way that IE/DOM does things.
function getIELayerClipValues(str)
{
  var clip = new Array();
  var i;

  // Parse out the clipping values for IE layers.
  i = str.indexOf("(");
  clip[0] = parseInt(str.substring(i + 1, str.length), 10);
  i = str.indexOf(" ", i + 1);
  clip[1] = parseInt(str.substring(i + 1, str.length), 10);
  i = str.indexOf(" ", i + 1);
  clip[2] = parseInt(str.substring(i + 1, str.length), 10);
  i = str.indexOf(" ", i + 1);
  clip[3] = parseInt(str.substring(i + 1, str.length), 10);

  return(clip);
}





//-----------------------------------------------------------------------------
// Layer scrolling.
//-----------------------------------------------------------------------------

// Scroll a layer to a specific position.  Bound is a boolean, indicating if the
//   contents of the layer should be constrained to the size of the layer itself.
function scrollLayerTo(layerName, x, y, bound)
{
  var layer = getLayer(layerName);

  var dx = getLayerClipLeft(layerName) - x;
  var dy = getLayerClipTop(layerName) - y;

  scrollLayerBy(layerName, -dx, -dy, bound);
}


// Scroll a layer by a specified delta.  Bound is a boolean, indicating if the
//   contents of the layer should be constrained to the size of the layer itself.
function scrollLayerBy(layerName, dx, dy, bound)
{
  var layer = getLayer(layerName);

  var cl = getLayerClipLeft(layerName);
  var ct = getLayerClipTop(layerName);
  var cr = getLayerClipRight(layerName);
  var cb = getLayerClipBottom(layerName);

  if (bound)
  {
    if (cl + dx < 0)
      dx = -cl;
    else if (cr + dx > getLayerWidth(layerName))
      dx = getLayerWidth(layerName) - cr;

    if (ct + dy < 0)
      dy = -ct;
    else if (cb + dy > getLayerHeight(layerName))
      dy = getLayerHeight(layerName) - cb;
  }

  clipLayer(layerName, cl + dx, ct + dy, cr + dx, cb + dy);
  moveLayerBy(layerName, -dx, -dy);
}






//-----------------------------------------------------------------------------
// Layer event handling.
//
// Notes:
//   Only visible layers can accept events.  In the case of two stacked
//     layers, only the topmost one (highest Z-index) is going to receive the
//     event.
//   Event functions should be passed in as a reference to the function -- that
//     is, without quotes or parentheses.
//   isInCapturePhase refers to whether or not the event is caught and handled
//     during the "capture" phase (NS6) -- true -- or during the normal/bubbling
//     phase -- false.  Simple event handling paradigms should go with true,
//     where more complex ones might want to consider going with false.
//
// Example:
//   setLayerMouseOver("myLayer", myLayerFcn, true);
//-----------------------------------------------------------------------------

// Assigns an event handler for mouseover events
function setLayerMouseOver(layerName, eventFcn, isInCapturePhase)
{
  var layer = getLayer(layerName);

  if ((browser.isNS6 || browser.isNS7 || browser.isMoz09 || browser.isMoz10))
  {
    layer.addEventListener("mouseover", eventFcn, isInCapturePhase);
  }
  if (browser.isNS47x)
  {
    layer.captureEvents(Event.MOUSEOVER);
    layer.onmouseover = eventFcn;
  }
  if (browser.isIE60 || browser.isIE55 || browser.isIE50)
  {
    layer.attachEvent("onmouseover", eventFcn);
  }
}


// Assigns an event handler to mouseout events in a given layer
function setLayerMouseOut(layerName, eventFcn, isInCapturePhase)
{
  var layer = getLayer(layerName);

  if (browser.isNS6 || browser.isNS7 || browser.isMoz09 || browser.isMoz10)
  {
    layer.addEventListener("mouseout", eventFcn, isInCapturePhase);
  }
  if (browser.isNS47x)
  {
    layer.captureEvents(Event.MOUSEOUT);
    layer.onmouseout = eventFcn;
  }
  if (browser.isIE60 || browser.isIE55 || browser.isIE50)
  {
    layer.attachEvent("onmouseout", eventFcn);
  }
}


// Assigns an event handler to mousemove events in the given layer
function setLayerMouseMove(layerName, eventFcn, isInCapturePhase)
{
  var layer = getLayer(layerName);

  if (browser.isNS6 || browser.isNS7 || browser.isMoz09 || browser.isMoz10)
  {
    layer.addEventListener("mousemove", eventFcn, isInCapturePhase);
  }
  if (browser.isNS47x)
  {
    layer.captureEvents(Event.MOUSEMOVE);
    layer.onmousemove = eventFcn;
  }
  if (browser.isIE60 || browser.isIE55 || browser.isIE50)
  {
    layer.attachEvent("onmousemove", eventFcn);
  }
}


// Assigns an event handler to mousedown events in the given layer
function setLayerMouseDown(layerName, eventFcn, isInCapturePhase)
{
  var layer = getLayer(layerName);

  if (browser.isNS6 || browser.isNS7 || browser.isMoz09 || browser.isMoz10)
  {
    layer.addEventListener("mousedown", eventFcn, isInCapturePhase);
  }
  if (browser.isNS47x)
  {
    layer.captureEvents(Event.MOUSEDOWN);
    layer.onmousedown = eventFcn;
  }
  if (browser.isIE60 || browser.isIE55 || browser.isIE50)
  {
    layer.attachEvent("onmousedown", eventFcn);
  }
}


// Assigns an event handler to mouseup events in the given layer
function setLayerMouseUp(layerName, eventFcn, isInCapturePhase)
{
  var layer = getLayer(layerName);

  if (browser.isNS6 || browser.isNS7 || browser.isMoz09 || browser.isMoz10)
  {
    layer.addEventListener("mouseup", eventFcn, isInCapturePhase);
  }
  if (browser.isNS47x)
  {
    layer.captureEvents(Event.MOUSEUP);
    layer.onmouseup = eventFcn;
  }
  if (browser.isIE60 || browser.isIE55 || browser.isIE50)
  {
    layer.attachEvent("onmouseup", eventFcn);
  }
}
