///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// 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
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////

//declaring the class
var gxDragBox = Class.create();
gxDragBox.prototype = {

initialize: function(ele, styleClass, boxStart, boxEnd) {
  ele = xGetElementById(ele);
  this.styleClass = styleClass;
  this.boxStart = boxStart;
  this.boxEnd = boxEnd;
  this.originX = null;
  this.originY = null;
  this.target = ele;
  this.box = document.createElement('DIV');
  xHide(this.box);
  this.box.style.position = 'absolute';
  this.box.style.lineHeight = '1px';
  this.box.style.fontSize = '1px';
  this.box.className = this.styleClass;
  xParent(ele).appendChild(this.box);
  this.boxActive = false;

  xAddEventListener(ele, 'mouseup', this.mouseUp.bindAsEventListener(this));
  xAddEventListener(ele, 'mousedown', this.mouseDown.bindAsEventListener(this));
},
     
mouseDown: function(evt) {
  var xe = new xEvent(evt);
  if (!this.boxActive) {
    xPreventDefault(evt);
    if (this.boxStart)
      this.boxStart(xe.offsetX, xe.offsetY);

    this.originX = xe.offsetX;
    this.originY = xe.offsetY;
    gxMoveAndResize(this.box, this.originX, this.originY, this.originX+1, this.originY+1);
    xShow(this.box);
    xAddEventListener(this.box, 'mousemove', this.mouseMoveBox.bindAsEventListener(this));
    xAddEventListener(this.box, 'mouseup', this.mouseUpBox.bindAsEventListener(this));
    xAddEventListener(this.target, 'mousemove', this.mouseMove.bindAsEventListener(this));
    this.boxActive = true;
  }
},

mouseMove: function(evt) {
  var xe = new xEvent(evt);
  var x;
  var y;
  xPreventDefault(evt);
  if (xe.target != this.box) {
    x = xe.offsetX;
    y = xe.offsetY;
  }
  else {  // IE only. Event of transparent top layer received.
    x = Math.max(0, xe.offsetX + xLeft(this.box));
    y = Math.max(0, xe.offsetY + xTop(this.box));
  }
  box = this.box;
  gxMoveAndResize(box, this.originX, this.originY, x, y);
},

mouseUp: function(evt) {
  var xe = new xEvent(evt);
  xPreventDefault(evt);
  var box = this.box;
  if (this.boxEnd) {
    var x = xe.offsetX < 0 ? this.originX+1 : xe.offsetX;  // IE returns -2 on single click (no drag) 
    var y = xe.offsetY < 0 ? this.originY+1 : xe.offsetY;  // IE returns -2 on single click (no drag) 
    this.boxEnd(this.originX, this.originY, x, y);
  }
  xHide(box);
  xParent(box).removeChild(box);
  this.box = null;
},

mouseMoveBox: function(evt) {
  var xe = new xEvent(evt);
  var box = this.box;
  if (this.boxActive) {
    xPreventDefault(evt);
    var x = xLeft(box) + xe.offsetX;
    var y = xTop(box) + xe.offsetY;
    if (x >= 0  &&  y >= 0  &&  x < xWidth(this.target)  &&  y < xHeight(this.target))  
      gxMoveAndResize(box, this.originX, this.originY, x, y);
  }
},

mouseUpBox: function(evt) {
  xPreventDefault(evt);
  xe = new xEvent(evt);
  box = this.box;
  if (this.boxEnd) {
    this.boxEnd(this.originX, this.originY, xLeft(box) + xe.offsetX, xTop(box) + xe.offsetY);
  }
  xHide(box);
  this.boxActive = false;
}
};

///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
// 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='';
}



