function kbd_standardsCompliance() 
{

  // Note: Despite the preferred use of object based feature detection, supporting non-standard browsers 
  // is not worth the development and maintenance costs in this instance.

  this.isIE = false;
  this.isW3C = false;

  if (navigator.userAgent.indexOf('MSIE') >= 0) 
  {
    // non-standards compliant support
    this.isIE = true
  } else {
    // treat all other browser types as W3C compliant
    this.isW3C = true
  }

}

var associativeClass = function () 
{
  this[0] = new Object ();
}

var compliance = new kbd_standardsCompliance ();
var elObj = new Object ();
var ac = new associativeClass ();

var key = function (id, value) 
{
  var i = 0;
  for (el in ac) 
  {
    if (ac[el].node == id) 
    {
      i = parseInt(el);
    } else {
      i = parseInt(el)+1;
      ac[i] = new Object ();
      break; // IE hack
    }
  }   
  ac[i].node = id;
  ac[i].dragType = value;
}

var kbd_DragObjectAPI = function (id, dragType)
{
  if (document.getElementById(id)) 
  {
    var value = (dragType) ? dragType.toLowerCase() : 'fixed'
    key (id, value);     
  }
}

var kbd_DragObjectAPIProperty = function (id, dragType)
{
  for (el in ac) 
  {
    if (ac[el].node == id) return ac[el].dragType;
  }

  var value = (dragType) ? dragType.toLowerCase() : 'fixed';

  return value;
}

var kbd_DragObject = function (event, id, dragType)
{

  if (document.getElementById(id))
  {

    elObj.elNode = document.getElementById(id);
    elObj.elDrag = kbd_DragObjectAPIProperty(id, dragType);

    if (elObj.elDrag === 'sticky' || elObj.elDrag === 'float')
    {

      // Get current cursor position
      var x = (compliance.isW3C) ? event.clientX + window.scrollX : window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
      var y = (compliance.isW3C) ? event.clientY + window.scrollY : window.event.clientY + document.documentElement.scrollTop + document.body.scrollTop;

      // Get the current starting positions
      elObj.cursorStartX = x;
      elObj.cursorStartY = y;
      elObj.elStartLeft = kbd_PosX();
      elObj.elStartTop = kbd_PosY();

      // initialise the mouse events
      if (compliance.isW3C) 
      {
        document.addEventListener("mousemove", kbd_Drag,   true);
        document.addEventListener("mouseup",   kbd_DragHalt, true);
        event.preventDefault();
      } else {
        document.attachEvent("onmousemove", kbd_Drag);
        document.attachEvent("onmouseup",   kbd_DragHalt);
        window.event.cancelBubble = true;
        window.event.returnValue = false;
      }
    }

  }
}

var kbd_PosX = function ()
{
  var x = (elObj.elNode.style.left) ? elObj.elNode.style.left : kbd_ExtractPosX();
  return parseInt(x,10);
}

var kbd_PosY = function ()
{
  var y = (elObj.elNode.style.top) ? elObj.elNode.style.top : kbd_ExtractPosY();
  return parseInt(y,10);
}

var kbd_ExtractPosX = function ()
{

  var posX = elObj.elNode.left;

  if (window.getComputedStyle) 
  {
    posX = getComputedStyle (elObj.elNode, null).left;
  } else if (elObj.elNode.currentStyle) {
    posX = elObj.elNode.currentStyle.left;
  } else {
    posX = elObj.elNode.style.left;
  }

  return posX;

}

var kbd_ExtractPosY = function ()
{

  var posY = elObj.elNode.top;

  if (window.getComputedStyle) 
  {
    posY = getComputedStyle (elObj.elNode, null).top;
  } else if (elObj.elNode.currentStyle) {
    posY = elObj.elNode.currentStyle.top;
  } else {
    posY = elObj.elNode.style.top;
  }

  return posY;

}

var kbd_Drag = function (event) 
{

  // get the current cursor position
  var x = (compliance.isW3C) ? event.clientX + window.scrollX : window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
  var y = (compliance.isW3C) ? event.clientY + window.scrollY : window.event.clientY + document.documentElement.scrollTop + document.body.scrollTop;

  // Move drag element by the same amount the cursor has moved.
  elObj.elNode.style.left = (elObj.elStartLeft + x - elObj.cursorStartX) + "px";
  elObj.elNode.style.top  = (elObj.elStartTop  + y - elObj.cursorStartY) + "px";

  if (compliance.isW3C) 
  {
    event.preventDefault();
  } else {
    window.event.cancelBubble = true;
    window.event.returnValue = false;
  }

}

var kbd_DragHalt = function (event) 
{

  // if sticky slid back to the starting point
  if (elObj.elDrag === 'sticky') kbd_SlideHome();

  // Stop capturing mousemove and mouseup events.
  if (compliance.isW3C) 
  {
    document.removeEventListener("mousemove", kbd_Drag,   true);
    document.removeEventListener("mouseup",   kbd_DragHalt, true);
  } else {
    document.detachEvent("onmousemove", kbd_Drag);
    document.detachEvent("onmouseup",   kbd_DragHalt);
  }

}

var kbd_SlideHome = function ()
{				

  // get the current position
  var x = kbd_PosX();
  var y = kbd_PosY();

  // get slide x value
  var slideX = Math.round(Math.abs(Math.max(x, elObj.elStartLeft) - Math.min(x, elObj.elStartLeft)) / 10);		
  // get slide y value
  var slideY = Math.round(Math.abs(Math.max(y, elObj.elStartTop) - Math.min(y, elObj.elStartTop)) / 10);
		
  if (slideY < 3 && Math.abs(slideX) < 10) slideY = 3;
  if (slideX < 3 && Math.abs(slideY) < 10) slideX = 3;

  // make slide value negative if start position is greater than current position
  if(x > elObj.elStartLeft) slideX *= -1;
  if(y > elObj.elStartTop) slideY *=- 1;
		
  // change current x and y
  x = x + slideX;	
  y = y + slideY;

  // if x or y is close to elObj.elStartLeft or elObj.elStartTop, make x equal to elObj.elStartLeft or y equal to elObj.elStartTop
  if (Math.max(x, elObj.elStartLeft) - Math.min(x, elObj.elStartLeft) < 4) x = elObj.elStartLeft;
  if (Math.max(y, elObj.elStartTop) - Math.min(y, elObj.elStartTop) < 4) y = elObj.elStartTop;

  // move drag elements
  elObj.elNode.style.left = x + 'px';
  elObj.elNode.style.top = y + 'px';	

  // if current posuition is not the start position recall this function
  if (x != elObj.elStartLeft || y != elObj.elStartTop)setTimeout('kbd_SlideHome()',5);

}
