///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxPan
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxEnablePan(ele, panStart, panEnd, pan) {
  ele = xGetElementById(ele);
  ele.gxPanStart = panStart;
  ele.gxPanEnd = panEnd;
  ele.gxPan = pan;
  if (ele.useMap) {
    if (ele.useMap.substr(0,1) == '#') {
      imageMapElem = xGetElementById(ele.useMap.substring(1,ele.useMap.length));
      if (imageMapElem == null)
        alert('gxEnablePan: image map specified, but element could not be found');
      else {
        areas = imageMapElem.areas;
        dragFunc = function(ele2, dx, dy) {   
          xMoveTo(ele, xLeft(ele) + dx, xTop(ele) + dy);
          xClip(ele, -xTop(ele), xWidth(ele)-xLeft(ele), xHeight(ele)-xTop(ele), -xLeft(ele));
        };
        count = 0;
        for (var i = areas.length-1; i >= 0; i--)
          xEnableDrag(areas[i], panStart, dragFunc, panEnd);
      }
    }
    else {
      alert('gxEnablePan: non-local image maps are not supported');
    }
  }
  else {
    xEnableDrag(ele, gxPanStart, gxPan, gxPanEnd);
  }
}

function gxPan(ele, dx, dy) {
  xMoveTo(ele, xLeft(ele) + dx, xTop(ele) + dy);
  xClip(ele, -xTop(ele), xWidth(ele)-xLeft(ele), xHeight(ele)-xTop(ele), -xLeft(ele));
  if (ele.gxPan)
    ele.gxPan(dx, dy);
}

function gxPanStart(ele, pageX, pageY) {
  ele.gxPanStartX = pageX;
  ele.gxPanStartY = pageY;
  if (ele.gxPanStart)
    ele.gxPanStart(pageX, pageY);
}

function gxPanEnd(ele, pageX, pageY) {
  if (ele.gxPanEnd) 
    ele.gxPanEnd(pageX - ele.gxPanStartX, pageY - ele.gxPanStartY); 
}

function gxDisablePan(ele) {
  xDisableDrag(ele);
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxTooltip
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxTooltip(uTimeout, parent, x, y, sStyle, sId, sHTML, afterHide)
{
  if (document.getElementById && document.createElement &&
      document.body && document.body.appendChild)
  { 
    // create popup element
    var e = document.createElement('DIV');
    this.ele = e;
    e.id = sId;
    e.style.position = 'relative';
    e.className = sStyle;
    e.innerHTML = sHTML;
    parent.appendChild(e);
    xMoveTo(e, x, y);
    xShow(e);
    this.open = true;
    this.tmr = xTimer.set('timeout', this, 'timeout', uTimeout);
    this.afterHide = afterHide;
  } 
} 

// methods
gxTooltip.prototype.hide = function()
{
  var e = this.ele;
  xParent(e, true).removeChild(e);
  this.open = false;
  this.tmr.stop();
};

gxTooltip.prototype.timeout = function() 
{
  this.hide();
  if (this.afterHide)
    eval(this.afterHide);
};

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxMapTip
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxMapTip(ele, tips, maxDist, timeout, styleClass, offsetX, offsetY, hasLink, beforeShow, afterHide) { 
  ele = xGetElementById(ele);
  if (!ele)
    alert('gxMapTip: element not found');
  this.tips = tips;
  this.hasLink = hasLink;
  this.maxDist = maxDist;
  this.timeout = timeout;
  this.styleClass = styleClass;
  this.offsetX = offsetX;
  this.offsetY = offsetY;
  this.beforeShow = beforeShow;
  this.afterHide = afterHide;
  this.current = null;
  this.enabled = true;
  ele.mapTipObj = this;
  xAddEventListener(ele, 'mousemove', this.mouseMove);
  xAddEventListener(ele, 'mouseout', this.mouseOut);
  if (hasLink)
    xAddEventListener(ele, 'click', this.click);
}

gxMapTip.prototype.click = function(evt) {
  xe = new xEvent(evt);
  mapTip = xe.target.mapTipObj;
  if (mapTip.enabled) {
    nearestTipIndex = mapTip.getNearest(xe.offsetX, xe.offsetY, mapTip);  
    if (nearestTipIndex != null  &&  mapTip.tips[nearestTipIndex+3]) {
      eval(mapTip.tips[nearestTipIndex+3]);
    }
  }
}

gxMapTip.prototype.getNearest = function(x, y, mapTip) {
    tips = mapTip.tips;
    inXRange = false;
    found = false;
    var minDistSq;
    var foundIndex = null;
    increment = 3;
    if (mapTip.hasLink)
      increment = 4;
    for (var i = tips.length-increment; i >= 0; i-=increment) {
      if (Math.abs(x - tips[i]) < mapTip.maxDist) {
        inXRange = true;
        if (Math.abs(y - tips[i+1]) < mapTip.maxDist) {
          distSq = Math.abs(x - tips[i])*Math.abs(x - tips[i]) + Math.abs(y - tips[i+1])*Math.abs(y - tips[i+1]); 
          if (!found  ||  distSq < minDistSq) {
            minDistSq = distSq;
            foundIndex = i;
            found = true;
          }
        }
      } 
      else if (inXRange)
        break;
    }
    
    if (found)
      return foundIndex;
    else 
      return null;
}

gxMapTip.prototype.mouseMove = function(evt) {
  xe = new xEvent(evt);
  if (xe.target.mapTipObj) { // For IE only. Is not defined if event of transparent layer above received.
      mapTip = xe.target.mapTipObj;
	  if (mapTip.enabled) {
	    nearestTipIndex = mapTip.getNearest(xe.offsetX, xe.offsetY, mapTip);
	    current = mapTip.current;
	
	    if ((nearestTipIndex != null) &&  (!current  ||  !current.open  ||  current.id != nearestTipIndex)) {
	      if (current  &&  current.open)
	        current.hide();
	      else if (mapTip.beforeShow)
            eval(mapTip.beforeShow);
            
	      mapTip.current = new gxTooltip(
	         mapTip.timeout,  
	         xParent(xe.target),
	         xe.offsetX + mapTip.offsetX,
	         xe.offsetY + mapTip.offsetY,
	         mapTip.styleClass,  
	         nearestTipIndex,           
	         tips[nearestTipIndex+2],
             mapTip.afterHide);  
	    }
	
	    if ((nearestTipIndex == null)  &&  current  &&  current.open) {
	      current.hide();
          if (mapTip.afterHide)
            eval(mapTip.afterHide);
        }
	  }
  }
};

/*
gxMapTip.prototype.mouseMove = function(evt) {
  xe = new xEvent(evt);
  mapTip = xe.target.mapTipObj;
  if (mapTip.enabled) {
    tips = mapTip.tips;
    current = mapTip.current;
    inXRange = false;
    found = false;
    var minDistSq;
    var foundIndex;
    for (var i = tips.length-3; i >= 0; i-=3) {
      if (Math.abs(xe.offsetX - tips[i]) < mapTip.maxDist) {
        inXRange = true;
        if (Math.abs(xe.offsetY - tips[i+1]) < mapTip.maxDist) {
          distSq = Math.abs(xe.offsetX - tips[i])*Math.abs(xe.offsetX - tips[i]) + Math.abs(xe.offsetY - tips[i+1])*Math.abs(xe.offsetY - tips[i+1]); 
          if (!found  ||  distSq < minDistSq) {
            minDistSq = distSq;
            foundIndex = i;
            found = true;
          }
        }
      } 
      else if (inXRange)
        break;
    }

    if (found  &&  (!current  ||  !current.open  ||  current.id != foundIndex)) {
	    if (current  &&  current.open)
	      current.hide();
	    
	    mapTip.current = new gxTooltip(
	       mapTip.timeout,  
	       xParent(xe.target),
	       xe.offsetX + mapTip.offsetX,
	       xe.offsetY + mapTip.offsetY,
	       mapTip.styleClass,  
	       foundIndex,           // id
	       tips[foundIndex+2]);  // tooltip content (HTML)
    }

    if (!found  &&  current  &&  current.open)
      current.hide();
  }
};*/

gxMapTip.prototype.mouseOut = function(evt) {
  xe = new xEvent(evt);
  if (xe.target  &&  xe.target.mapTipObj) {
	  mapTip = xe.target.mapTipObj;
	  current = mapTip.current;
	  if (current  &&  current.open) {
	    current.hide();
        if (mapTip.afterHide)
          eval(mapTip.afterHide);
      }
  }
};

gxMapTip.prototype.setEnabled = function(enabled) {
  if (this.enabled != enabled) {
    this.enabled = enabled;
    if (!enabled  &&  this.current  &&  this.current.open) {
      this.current.hide();
      if (this.afterHide)
        eval(this.afterHide);
    }
  }
}




///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxDragBox
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxDragBox(ele, styleClass, boxStart, boxEnd) {
  ele = xGetElementById(ele);
  this.styleClass = styleClass;
  this.boxStart = boxStart;
  this.boxEnd = boxEnd;
  this.box = null;
  this.originX = null;
  this.originY = null;
  this.target = ele;
  ele.gxDragBox = this;
  xAddEventListener(ele, 'mousedown', this.mouseDown);
  xAddEventListener(ele, 'mouseup', this.mouseUp);
  xAddEventListener(ele, 'mousemove', this.mouseMove);
}

gxDragBox.prototype.mouseDown = function(evt) {
  xe = new xEvent(evt);
  gxDragBox = xe.target.gxDragBox;
  if (!gxDragBox.box) {
    xPreventDefault(evt);
    if (gxDragBox.boxStart)
      gxDragBox.boxStart(xe.offsetX, xe.offsetY);

    var box = document.createElement('DIV');
    gxDragBox.box = box;
    gxDragBox.originX = xe.offsetX;
    gxDragBox.originY = xe.offsetY;
    
    // choose a different variable name than 'gxDragBox' to allow a distinction 
    // of event targets in gxDragBox.mouseMove()
    box.gxDragBoxBox = gxDragBox;   
    box.style.position = 'relative';
    box.className = gxDragBox.styleClass;
    xParent(xe.target).appendChild(box);
    xWidth(box, 1);
    xHeight(box, 1);
    xMoveTo(box, xe.offsetX, xe.offsetY);
    xShow(box);
    xAddEventListener(box, 'mousemove', gxDragBox.mouseMoveBox);
    xAddEventListener(box, 'mouseup', gxDragBox.mouseUpBox);
  }
}


gxDragBox.prototype.mouseMove = function(evt) {
  var xe = new xEvent(evt);
  var x;
  var y;
  var gxDragBox;
  if (xe.target.gxDragBox) {
    gxDragBox = xe.target.gxDragBox;
    x = xe.offsetX;
    y = xe.offsetY;
  }
  else if (xe.target.gxDragBoxBox) {  // IE only. Event of transparent top layer received.
    gxDragBox = xe.target.gxDragBoxBox;
    x = xe.offsetX + xLeft(gxDragBox.box);
    y = xe.offsetY + xTop(gxDragBox.box);
  }
  if (gxDragBox) {
	  box = gxDragBox.box;
      xPreventDefault(evt);
      gxMoveAndResize(box, gxDragBox.originX, gxDragBox.originY, 
                      x, y);
  }
}

gxDragBox.prototype.mouseUp = function(evt) {
  xPreventDefault(evt);
  var xe = new xEvent(evt);
  var gxDragBox = xe.target.gxDragBox;
  var box = gxDragBox.box;
  if (gxDragBox.boxEnd) {
    gxDragBox.boxEnd(gxDragBox.originX, gxDragBox.originY, xe.offsetX, xe.offsetY);
  }
  xHide(box);
  xParent(box).removeChild(box);
  gxDragBox.box = null;
}

gxDragBox.prototype.mouseMoveBox = function(evt) {
  var xe = new xEvent(evt);
  var gxDragBox = xe.target.gxDragBoxBox;
  var box = gxDragBox.box;
  if (box) {
    xPreventDefault(evt);
    var x = xLeft(box) + xe.offsetX;
    var y = xTop(box) + xe.offsetY;
    if (x >= 0  &&  y >= 0  &&  x < xWidth(gxDragBox.target)  &&  y < xHeight(gxDragBox.target))  
      gxMoveAndResize(box, gxDragBox.originX, gxDragBox.originY, x, y);
  }
}

gxDragBox.prototype.mouseUpBox = function(evt) {
  xPreventDefault(evt);
  xe = new xEvent(evt);
  gxDragBox = xe.target.gxDragBoxBox;
  box = gxDragBox.box;
  if (gxDragBox.boxEnd) {
    gxDragBox.boxEnd(gxDragBox.originX, gxDragBox.originY, xLeft(box) + xe.offsetX, xTop(box) + xe.offsetY);
  }
  xHide(box);
  xParent(box).removeChild(box);
  gxDragBox.box = null;
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxControlSelect
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxControlSelect(inputEle, selectEle, onChange) {
  inputEle = xGetElementById(inputEle);
  if (!inputEle)
    alert('gxControlSelect: input element not found');
  selectEle = xGetElementById(selectEle);
  if (!selectEle)
    alert('gxControlSelect: select element not found');
  this.inputEle = inputEle;
  this.selectEle = selectEle;
  this.onChangeFunc = onChange;
  inputEle.controlSelectObj = this;
  xAddEventListener(inputEle, 'keyup', this.keyUp);
}

gxControlSelect.prototype.keyUp = function(evt) {
  xe = new xEvent(evt);
  controlSelect = xe.target.controlSelectObj;
  sel = controlSelect.selectEle;
  len = sel.options.length;
  tipped = controlSelect.inputEle.value;
  if (tipped.length > 0) {
    for (i = 0; i < len; i++) {
      if (sel.options[i].text.substr(0, tipped.length).toLowerCase() == tipped.toLowerCase()) {
        sel.options[i].selected = true;
        if (controlSelect.onChangeFunc)
          controlSelect.onChangeFunc(sel);
        break;    
      }
    }
  }
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxMasterSlaveSelect
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxMasterSlaveSelect(masterEle, slaveEle, dataEle) {
  masterEle = xGetElementById(masterEle);
  if (!masterEle)
    alert('gxMasterSlaveSelect: master element not found');
  slaveEle = xGetElementById(slaveEle);
  if (!slaveEle)
    alert('gxMasterSlaveSelect: slave element not found');
  dataEle = xGetElementById(dataEle);
  if (!dataEle)
    alert('gxMasterSlaveSelect: data element not found');
  this.masterEle = masterEle;
  this.slaveEle = slaveEle;
  this.dataEle = dataEle;

  this.data = new Array();
  var io = 0;
  var og = dataEle.firstChild;
  var ig = 0;

  while (og) {
    if (og.nodeName.toLowerCase() == 'optgroup') {
      io = 0;
      this.data[ig] = new Array();
      op = og.firstChild;
      while (op) {
        if (op.nodeName.toLowerCase() == 'option') {
          this.data[ig][io] = op.innerHTML;
          io++;
        }
        op = op.nextSibling;
      }
      ig++;
    }
    og = og.nextSibling;
  }

  masterEle.masterSlaveSelectObj = this;
  xAddEventListener(masterEle, 'change', this.change);
  this.updateSlave(masterEle);
}

gxMasterSlaveSelect.prototype.updateSlave = function(masterEle) {
  _this = masterEle.masterSlaveSelectObj;
  selIndex = _this.masterEle.selectedIndex;
  
  // clear existing
  for (i = _this.slaveEle.options.length-1; i >= 0; i--) {
    _this.slaveEle.options[i].selected = false;
    _this.slaveEle.options[i] = null;
  }
  
  if (selIndex != -1) {
	for (io=0; io<_this.data[selIndex].length; io++) {
	  op = new Option(_this.data[selIndex][io]);
	  _this.slaveEle.options[io] = op;
	}
  }
}

gxMasterSlaveSelect.prototype.change = function(evt) {
  xe = new xEvent(evt);
  _this = xe.target.masterSlaveSelectObj;
  _this.updateSlave(_this.masterEle);
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// gxMasterSlaveSelectArray
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxMasterSlaveSelectArray(masterEle, slaveEle, data) {
  masterEle = xGetElementById(masterEle);
  if (!masterEle)
    alert('gxMasterSlaveSelectArray: master element not found');
  slaveEle = xGetElementById(slaveEle);
  if (!slaveEle)
    alert('gxMasterSlaveSelectArray: slave element not found');
  if (!data)
    alert('gxMasterSlaveSelectArray: data array not found');
  this.masterEle = masterEle;
  this.slaveEle = slaveEle;
  this.data = data;
  masterEle.masterSlaveSelectArrayObj = this;
  xAddEventListener(masterEle, 'change', this.change);
  this.updateSlave(masterEle);
}

gxMasterSlaveSelectArray.prototype.updateSlave = function(masterEle) {
  var _this = masterEle.masterSlaveSelectArrayObj;
  var selIndex = _this.masterEle.selectedIndex;
  
  // clear existing
  for (var i = _this.slaveEle.options.length-1; i >= 0; i--) {
    _this.slaveEle.options[i].selected = false;
    _this.slaveEle.options[i] = null;
  }
  
  if (selIndex != -1) {
	for (var i = 0; i < _this.data[selIndex].length; i++) {
	  var op = new Option(_this.data[selIndex][i]);
//new Option() kennt vier Parameter von denen die drei letzten Parameter optional sind.
//1. text = angezeigter Text in der Liste
//2. value = zu übertragender Wert der Liste (optional)
//3. defaultSelected = true übergeben, wenn der Eintrag der defaultmäßig vorselektierte Eintrag sein soll, sonst false (optional)
//4. selected = true übergeben, wenn der Eintrag selektiert werden soll (optional)    
	  _this.slaveEle.options[i] = op;
    }
  }
}

gxMasterSlaveSelectArray.prototype.change = function(evt) {
  xe = new xEvent(evt);
  _this = xe.target.masterSlaveSelectArrayObj;
  _this.updateSlave(_this.masterEle);
}

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// various gx tool functions
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

function gxPreventSubmitOnEnter(ele) {

  function keyPress(evt)
  {
    var xe = new xEvent(evt);
	if (xe.keyCode == 13) 
	  xPreventDefault(evt);
  }
  
  xAddEventListener(ele, 'keypress', keyPress);
}


function gxMoveAndResize(ele, x1, y1, x2, y2) {
  if (x2 < x1) {
    t = x2;
    x2 = x1;
    x1 = t;
  }
  if (y2 < y1) {
    t = y2;
    y2 = y1;
    y1 = t;
  }
  //window.status = 'moveAndResize: ' + x1 + ',' + y1 + ',' + (x2-x1) + ',' + (y2-y1);
  xMoveTo(ele, x1, y1);
  xResizeTo(ele, x2-x1, y2-y1);  
}


function gxGetURLArgNames()
{
  var idx = location.href.indexOf('?');
  var params = new Array();
  if (idx != -1) {
    var pairs = location.href.substring(idx+1, location.href.length).split('&');
    for (var i=0; i<pairs.length; i++) {
      nameVal = pairs[i].split('=');
      params[i] = nameVal[0];
    }
  }
  return params;
}

function gxGetURLParams() {
  
  var idx = location.href.indexOf('?');
  var params = new Object();
  if (idx != -1) {
    var pairs = location.href.substring(idx+1, location.href.length).split('&');
    for (var i=0; i<pairs.length; i++) {
      nameVal = pairs[i].split('=');
      params[nameVal[0]] = nameVal[1];
    }
  }
  return params;
}

function gxBuildParamString(params) {
  retVal = '';
  separator = '';
  for (var p in params) {
    retVal = retVal + separator + p + '=' + params[p];
    separator = '&';
  }
  if (retVal != '')
    retVal = '?' + retVal;
    
  return retVal;
}

function gxGetURLWithoutParams(loc) {
  var retVal;
  
  if (!loc)
    loc = location;
    
  var idx = loc.href.indexOf('?');
  if (idx != -1) 
    retVal = loc.href.substring(0, idx);
  else
    retVal = loc.href;
    
  return retVal;
}

function gxHideScrollBars() {  
  document.body.style.overflow='hidden';
}

function gxUnhideScrollBars() {
  document.body.style.overflow='';
}


