//DOM Wrapper Utility Class. Version 1.0.0
//Ralf Thompson, www.secavian.com
//Copyright 2005
//
//Public domain. users may use and modify as needed as
//long as original credit to this module is rendered.
//
//tested with the following browsers:
//  NS6, NS7
//  IE5_5, IE6
//  Opera 6, Opera 7
//  Firefox 1
function DHTMLUtility_Class(){
  this.eventObjects = new Array();
  this.activeEventObject = null;
  this.eventOffset = new Array();
  this.dragType = '';
  this.initializationCounter = 0;
  this.clipDragToWindow = true;
  this.VERTCOORD = 0;
  this.HORIZCOORD = 1;

  this.isDHTML = false;
  this.isID = false;

  if(window.document.getElementById){
  this.isID = true;
  this.isDHTML = true;
  }

  this.getDOMObject = function(objectID){
  try{
    if(objectID){
      if(this.isID){
        return document.getElementById(objectID);
      }
      else{
        return null;
      }
    }
    else{
      return null;
    }
  }catch(e){return null;}
  }

  this.getDOMStyleObject = function(objectID){
  try{
    if(objectID){
      if(this.isID){
        return document.getElementById(objectID).style;
      }
      else{
        return null;
      }
    }
    else{
      return null;
    }
  }catch(e){return null;}
  }

  this.getParentObject = function(object){
  try{
    return this.getDOMObject(object).parentNode;
  }catch(e){}
  }

  this.getBrowserAvailableHeight = function(){
  try{
    if(window.innerHeight){
      return window.innerHeight;
    }
    else if(document.body.clientHeight){
      return document.body.clientHeight;
    }
    else{
      return null;
    }
  }catch(e){return null}
  }

  this.getBrowserAvailableWidth = function(){
  try{
    if(window.innerWidth){
      return window.innerWidth;
    }
    else if(document.body.clientWidth){
      return document.body.clientWidth;
    }
    else{
      return null;
    }
  }catch(e){return null}
  }

  this.getInnerText = function(object, text){
  try{
    var obj = this.getDOMObject(object);
    if(obj.innerText != null){
      return obj.innerText;
    }
    else{
      return this.escapeHTML(obj.innerHTML);
      //return true;
    }
  }catch(e){return null;}
  }

  this.setInnerText = function(object, text){
  try{
    var obj = this.getDOMObject(object);
    if(('' + obj.innerText) == 'undefined'){
      obj.innerHTML = this.escapeHTML(text)
      return true;
    }
    else{
      obj.innerText = text;
      return true;
    }
  }catch(e){return false;}
  }

  this.getScrollHoriz = function(){
  try{
    if(window.pageXOffset != null){
      return window.pageXOffset;
    }
    else if(document.body.scrollLeft != null){
      return document.body.scrollLeft;
    }
    else{
      return null;
    }
  }catch(e){return null;}
  }

  this.getScrollVert = function(){
  try{
    if(window.pageYOffset != null){
      return window.pageYOffset;
    }
    else if(document.body.scrollTop != null){
      return document.body.scrollTop;
    }
    else{
      return null;
    }
  }catch(e){return null;}
  }

  this.scrollTo = function(offsetVert, offsetHoriz){
  try{
    if(isNaN(offsetVert) || isNaN(offsetHoriz)){
      return false;
    }
    var vert = parseInt(offsetVert);
    var horiz = parseInt(offsetHoriz);

    if(vert < 0){vert = 0;}
    if(horiz < 0){horiz = 0;}

    if(scrollTo){
      scrollTo(horiz, vert);
      return true;
    }
    else if(document.body.scrollTop){
      document.body.scrollTop = vert;
      document.body.scrollLeft = horiz;
      return true;
    }
    else{
      return false;
    }
  }catch(e){return false;}
  }

  this.setScrollVertTo = function(offsetVert){
  return this.scrollTo(offsetVert, this.getScrollHoriz());
  }

  this.setScrollHorizTo = function(offsetHoriz){
  return this.scrollTo( this.getScrollVert(), offsetHoriz);
  }

  this.scrollBy = function(vertAmt, horizAmt){
  try{
    if(isNaN(vertAmt) || isNaN(horizAmt)){
      return false;
    }
    var vert = this.getScrollVert() + parseInt(vertAmt);
    var horiz = this.getScrollHoriz() + parseInt(horizAmt);

    if(vert < 0){vert = 0;}
    if(horiz < 0){horiz = 0;}

    if(scrollTo){
      scrollTo(horiz, vert);
      return true;
    }
    else if(document.body.scrollTop){
      document.body.scrollTop = vert;
      document.body.scrollLeft = horiz;
      return true;
    }
    else{
      return false;
    }
  }catch(e){return false;}
  }

  this.scrollVertBy = function(vertAmt){
  return this.scrollBy(vertAmt, 0);
  }

  this.scrollHorizBy = function(horizAmt){
  return this.scrollBy(0, horizAmt);
  }

  this.getPosition = function(object){
  return this.getDOMStyleObject(object).position;
  }

  this.setPosition = function(object, value){
  try{
    this.getDOMStyleObject(object).position = value;
    return true;
  }catch(e){return false;}
  }

  this.getVisibility = function(object){
  try{
    return this.getDOMStyleObject(object).visibility;
  }catch(e){return null;}
  }

  this.setVisibility = function(object, value){
  try{
    this.getDOMStyleObject(object).visibility = value;
    return true;
  }catch(e){return false;}
  }

  this.getDisplay = function(object){
  try{
    return this.getDOMStyleObject(object).display;
  }catch(e){return null;}
  }

  this.setDisplay = function(object, value){
  try{
    this.getDOMStyleObject(object).display = value;
    return true;
  }catch(e){return false;}
  }

  this.getWidth = function(object){
  try{
    var width = this.getDOMStyleObject(object).width;
    if(width == ''){
      width = this.getDOMObject(object).offsetWidth;
    }
    return parseInt(width);
  }catch(e){return null;}
  }

  this.setWidth = function(object, width){
  try{
    if(isNaN(width)){
      return false;
    }
    this.getDOMStyleObject(object).width = parseInt(width);
    return true;
  }catch(e){return false;}
  }

  this.getHeight = function(object){
  try{
    var height = this.getDOMStyleObject(object).height;
    if(height == ''){
      height = this.getDOMObject(object).offsetHeight;
    }
    return parseInt(height);
  }catch(e){return null;}
  }

  this.setHeight = function(object, h){
  try{
    if(isNaN(h)){
      return false;
    }
      this.getDOMStyleObject(object).height = parseInt(h);
      return true;
  }catch(e){return false;}
  }

  this.getTop = function(object){
  try{
    var top = this.getDOMStyleObject(object).top;
    if(top == '' || top == 'auto'){
      top = this.getDOMObject(object).offsetTop;
    }
    return parseInt(top);
  }catch(e){return null;}
  }

  this.setTop = function(object, x){
  try{
    this.getDOMStyleObject(object).top = parseInt(0 + x);
    return true;
  }catch(e){return false;}
  }

  this.getLeft = function(object){
  try{
    var left = this.getDOMStyleObject(object).left;
    if(left == '' || left == 'auto'){
      left = this.getDOMObject(object).offsetLeft;
    }
    return parseInt(left);
  }catch(e){return null;}
  }

  this.setLeft = function(object, y){
  try{
    this.getDOMStyleObject(object).left = parseInt(0 + y);
    return true;
  }catch(e){return false;}
  }

  this.getRight = function(object){
  try{
    return this.getLeft(object) + this.getWidth(object);
  }catch(e){return null;}
  }

  this.getBottom = function(object){
  try{
    return this.getTop(object) + this.getHeight(object);
  }catch(e){return null;}
  }

  this.moveTo = function(object, x, y){
  try{
    var v = this.moveVertTo(object, x);
    var h = this.moveHorizTo(object, y);
    return v && h;
  }catch(e){return false;}
  }

  this.moveVertTo = function(object, x){
  try{
    return this.setTop(object, x);
  }catch(e){return false;}
  }

  this.moveHorizTo = function(object, y){
  try{
    return this.setLeft(object, y);
  }catch(e){return false;}
  }

  this.moveBy = function(object, x, y){
  try{
    var v = this.moveVertBy(object, x);
    var h = this.moveHorizBy(object, y);
    return v && h;
  }catch(e){return null;}
  }

  this.moveVertBy = function(object, x){
  try{
    var top = this.getTop(object);
    if(top != null){
    top += parseInt(0 + x);
    if(top < 0){
      top = 0;
    }
    return this.setTop(object, top);
    }
    else{
    return false;
    }
  }catch(e){return null;}
  }

  this.moveHorizBy = function(object, y){
  try{
    var left = this.getLeft(object) + y;
    if(left < 0){
      left = 0;
    }
    var obj = this.getDOMObject(object);
    if(typeof obj.offsetLeft == 'string'){
      left += 'px';
    }
    return this.setLeft(object, left);
  }catch(e){return false;}
  }

  this.registerEventObject = function(source, target, action){
  try{
    var ec = new DHTMLUtility_EventClass(source, target, action);
    this.eventObjects[this.eventObjects.length] = ec;
    return this.eventObjects.length;
  }catch(e){return -1};
  }

  this.getZIndex = function(object){
  try{
    return parseInt(this.getDOMStyleObject(object).zIndex);
  }catch(e){return null;}
  }

  this.setZIndex = function(object, z){
  try{
    this.getDOMStyleObject(object).zIndex = parseInt(z);
    return true;
  }catch(e){return false;}
  }

  this.getEvent = function(evt){
  return  (evt) ? evt : ((window.event) ? window.event : null);
  }

  this.getTarget = function(evt){
  return  (evt.target) ? evt.target : evt.srcElement;
  }

  this.setEventOffsetCoords = function(evt, parent){
  var obj = this.activeEventObject;
  var left = 0;
  var top = 0;
  if(evt.pageX){
    left = evt.pageX - ((typeof obj.offsetLeft != 'undefined') ? obj.offsetLeft : obj.left);
    top = evt.pageY - ((typeof obj.offsetTop != 'undefined') ? obj.offsetTop : obj.top);
  }
  else if((typeof evt.offsetX) != 'undefined'){
    left  = evt.offsetX - ((evt.offsetX < -2) ? 0 : document.body.scrollLeft);
    left -= (parent && parent.scrollLeft) ? parent.scrollLeft : 0;

    top  = evt.offsetY - ((evt.offsetY < -2) ? 0 : document.body.scrollTop);
    top -= (parent && parent.scrollTop) ? parent.scrollTop : 0;
  }

  /*
  else if((typeof evt.clientX) != 'undefined'){
  left = evt.offsetX - ((typeof obj.offsetLeft != 'undefined') ? obj.offsetLeft : 0);
  top = evt.offsetY - ((typeof obj.offsetTop != 'undefined') ? obj.offsetTop : 0);
  }
  */

  this.eventOffset[this.HORIZCOORD] = left;
  this.eventOffset[this.VERTCOORD] = top;
  return true;
  }

  this.grabObject = function(evt){
  evt = this.getEvent(evt);
  if(evt){
    var objId = this.getTarget(evt).id;
    var coll = this.eventObjects;
    for(var i = 0; i < coll.length; i++){
      if(coll[i].sourceId == objId){

        switch(coll[i].action){
        
          case 'drag':
          case 'dragclip':
          case 'dragwindow':
            var targetId = coll[i].targetId;
            this.activeEventObject = this.getDOMObject(targetId);
            this.setZIndex(targetId, 100);
            this.setEventOffsetCoords(evt, this.getParentObject(targetId));
            this.dragType = coll[i].action;
            i = coll.length;
            break;

          case 'call':
            return eval(coll[i].callTarget);
            break;
        }
      }
    }
    if(document.body.setCapture){
      document.body.setCapture();
    }
    return false;
  }
  }

  this.dragObject = function(evt){
  if(this.activeEventObject){
    evt = this.getEvent(evt);
    var left = 0;
    var top = 0;
    var right = 0;
    var bottom = 0;
    var parentRight = 0;
    var parentBottom = 0;
    var eventLeft = 0;
    var eventTop = 0;
    var objId = this.activeEventObject.id;
    var parent = this.getParentObject(objId);

    if(typeof evt.pageX != 'undefined'){
      eventLeft = evt.pageX;
      eventTop = evt.pageY;
      left = eventLeft - this.eventOffset[this.HORIZCOORD];
      top = eventTop - this.eventOffset[this.VERTCOORD];
    }
    else if(evt.clientX || evt.clientY){
      eventLeft = evt.clientX;
      eventTop = evt.clientY;
      left = eventLeft - this.eventOffset[this.HORIZCOORD];
      top = eventTop - this.eventOffset[this.VERTCOORD];

      if(parent){
        left -= parent.offsetLeft;
        top -= parent.offsetTop;
      }
    }

    this.moveTo(this.activeEventObject.id, top, left);
    right = this.getRight(objId) + this.getLeft(parent.id);
    bottom = this.getBottom(objId) + this.getTop(parent.id);
    parentRight = this.getRight(parent.id);
    parentBottom = this.getBottom(parent.id);

    if(this.dragType == 'dragclip' && (parent)){
      if(top < 0){top = 0;}
      if(left < 0){left = 0;}
      if(right >= parentRight){
        left = this.getRight(parent.id) - this.getWidth(objId) - this.getLeft(parent.id);
      }
      if(bottom >= parentBottom){
        top = this.getBottom(parent.id) - this.getHeight(objId) - this.getTop(parent.id);
      }
    }

    //netscape workaround: NS 6/7 will not scroll the window if
    //an object is dragged outside the boundaries of the window.
    //when that happens, the object is no longer accessible and
    //the scroll bars no longer work. worse, once the object is
    //off the page, it is dropped and can't be dragged back
    //into the main screen even if the user doesn't release the
    //mouse button. annoying, to say the least
    if(this.clipDragToWindow){
      if(left < (0-parent.offsetLeft)){left = (0-parent.offsetLeft);}
      if(top < (0-parent.offsetTop)){top = (0-parent.offsetTop);}

      //right = left + this.getWidth(objId) + this.eventOffset[this.HORIZCOORD];
      //bottom = top + this.getHeight(objId) + this.eventOffset[this.VERTCOORD];
      //window.status = bottom + ' ' + document.body.offsetHeight + ' ';
      //
      //if(right > (document.body.offsetWidth - this.getScrollHoriz())){
      //  left = document.body.offsetWidth - this.getWidth(objId) - parent.offsetLeft;
      //}

      /*
      //this is not working because of different ways of showing and
      //allowing for scroll bars by different browsers
      if(eventLeft > this.getBrowserAvailableWidth()){
      left -= (eventLeft - this.getBrowserAvailableWidth());
      }
      if(eventTop > this.getBrowserAvailableHeight()){
      top -= (eventTop - this.getBrowserAvailableHeight());
      }
      //*/
    }
    this.moveTo(this.activeEventObject.id, top, left);

    evt.cancelBubble = true;
    return false;
  }
  }

  this.releaseObject = function(evt){
  if(this.activeEventObject){
    this.setZIndex(this.activeEventObject.id, 0);
    if(document.body.releaseCapture){
      document.body.releaseCapture();
    }
    this.activeEventObject = null;
  }
  return false;
  }

  this.getEventRolloverCoords = function(evt, parent){
  var coords = new Array();
  coords[this.HORIZCOORD] = (evt.pageX) ? evt.pageX : ((evt.clientX) ? evt.clientX : 0);
  coords[this.VERTCOORD] =  (evt.pageY) ? evt.pageY : ((evt.clientY) ? evt.clientY : 0);
  return coords;
  }

  this.enterObject = function(evt){
  evt = this.getEvent(evt);
  if(evt){
    var objId = this.getTarget(evt).id;
    var coll = this.eventObjects;
    for(var i = 0; i < coll.length; i++){
      if(coll[i].sourceId == objId){

        switch(coll[i].action){

          case 'showAsContext':
            var targetId = coll[i].targetId;
            var obj = this.getDOMStyleObject(targetId);
            obj.display = '';
            var coords = this.getEventRolloverCoords(evt, this.getDOMObject(coll[i].sourceId));
            this.setLeft(targetId, coords[this.HORIZCOORD]);
            this.setTop(targetId, coords[this.VERTCOORD]);
            i = coll.length;
            break;
        }
      }
    }
  }
  return false;
  }

  this.exitObject = function(evt){
  evt = this.getEvent(evt);
  if(evt){
    var objId = this.getTarget(evt).id;
    var coll = this.eventObjects;
    for(var i = 0; i < coll.length; i++){
      if(coll[i].sourceId == objId){

        switch(coll[i].action){

          case 'showAsContext':
            this.getDOMStyleObject(coll[i].targetId).display = 'none';
            i = coll.length;
            break;
        }
      }
    }
  }
  return false;
  }

  this.initialize = function(){
  this.initializeDOM();
  }

  this.initializeDOM = function(){
  if(document.body){
    this.initializeElement(document.body);
    for(var i = 0; i < document.body.childNodes.length; i++){
      this.initializeChild(document.body.childNodes[i]);
    }
  }
  }

  this.initializeChild = function(child){
  try{
    if(child){
      if(child.childNodes){
        for(var i = 0; i < child.childNodes.length; i++){
          this.initializeChild(child.childNodes[i]);
        }
      }
      this.initializeElement(child);
    }
  }catch(e){}
  }

  this.initializeElement = function(element){
  try{
    if(element && element.style){
      var s = element.style;
      if(s.overflow == ''){s.overflow = this.defaultOverflow;}
      if(s.top == ''){s.top = this.defaultTop;}
      if(s.left == ''){s.left = this.defaultLeft;}
      if(s.zIndex == ''){s.zIndex = this.defaultZIndex;}

      //netscape workaround: NS 6/7 has a tendency to resize unrelated
      //elements if they don't possess an id and width or height style
      //values. if an element does not have an id, give it one then
      //set it's width and height style values to its current offsetWidth
      //and defaultHeight values. this does not affect the other browsers
      //so it is applied universally - it may be appropriate down the road
      //to get browser specific but I'm trying to avoid that if at all
      //possible.
      if(!element.id){
        while(document.getElementById('object_' + this.initializationCounter)){
          this.initializationCounter++;
        }
        element.id = 'object_' + this.initializationCounter;
        if(s.width == ''){s.width = element.offsetWidth;}
        if(s.height == ''){s.height = element.defaultHeight;}
      }
    }
  }catch(e){};
  }

  this.escapeHTML = function(text){
  return ('' + text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  }

  this.defaultOverflow = 'visible';
  this.defaultTop = '0';
  this.defaultLeft = '0';
  this.defaultZIndex = 0;
}

function DHTMLUtility_EventClass(source, target, action){
  this.sourceId = source;
  this.targetId = target;
  this.action = action;
  this.callTarget = '';

  switch(action){
    case 'call':
      this.callTarget = target;
      break;

    default:
      break;
  }
}

function DHTMLUtilityClass_grabObject(evt){
  try{
    return DOM.grabObject(evt);
  }catch(e){return false;}
}

function DHTMLUtilityClass_dragObject(evt){
  try{
    return DOM.dragObject(evt);
  }catch(e){return false;}
}

function DHTMLUtilityClass_releaseObject(evt){
  try{
    return DOM.releaseObject(evt);
  }catch(e){return false;}
}

function DHTMLUtilityClass_onmouseover(evt){
  return DOM.enterObject(evt);
}

function DHTMLUtilityClass_onmouseout(evt){
  return DOM.exitObject(evt);
}

