 var tip = 
 '<g id="tGroup" transform="matrix(flipX 0 0 flipY xfrmX,xfrmY)" style="stroke:#000000;stroke-width:1" >' +
 '<path fill="#808080" d="M 20,15 L 1,1 L 15,25 L 15,hgt L wdth,hgt L wdth,15z"/></g>';

function SVGObject() {
  // 21197 - set to true to suppress interpolated tool tip values for restart markers.
  this.delta = 0;
  this.notip = false;
  this.nowline;
  this.hourglassOff = true;
  this.annotations;
  this.txt;
  this.aW;
  this.aH;
  this.log;
  this.powr;
  this.containerW;
  this.containerH;
  this.wpq;
  this.trace;
  this.status;
  this.statusTime;
  this.evtX;
  this.evtY;
  this.hourglass = null;
  this.tipTimer = 0;
  this.tipTimerOff = 0;
  this.indxs;
  this.intercepts;
  this.states;
  this.slopes;
  this.realx;
  this.segs;
  this.startTime;
  this.endTime;
  this.perPixels;
  this.tzRules;
  this.secsPerPixel;
  this.inverted;
  this.minvalsnd;
  this.maxvalsnd;
  this.actminvalsnd;
  this.actmaxvalsnd;
  this.dataTypes;
  this.numTraces;
  this.dispdigs;
  this.wpq;
  this.variables;
  this.clientX;
  this.clientY;
  this.clientH;
  this.clientW;
  this.clientX2;
  this.upperLeftX;
  this.lowerRightX;
  this.upperLeftY;
  this.lowerRightY;
  this.tipGroup;
  this.tipText;
  this.tipTime;
  this.tipRect;
  this.lastClientX     = 0;
  this.lastClientY     = 0;
  this.cursorMode      = false;
  this.boxstart        = 0;
  this.rtClickX        = 0;
  this.startx          = 0;
  this.starty          = 0;
  this.selectedCursorX = null;
  this.cursorArray     = new Array();
  this.zoomed          = false;
  this.svgdoc;
  this.svgScript;
  this.upperYs;
  this.upperXs;
  this.widths;
  this.height;
  this.orientation;
  this.rotation;
  this.rtClickY;
  
// annotation tooltip location adjustment
  this.wp_H;
  this.wp_W;
  this.vb_H;
  this.vb_W;
  this.vb_Ratio; // svg coordinates and webpart coordinates
  this.vb_Orientation = true; // true: horizontal(webpart width = svg width), false:vertical(webpart height = svg Height) 

// tooltip arrays
  this.tags = new Array();
  this.vals = new Array();
  this.mrkrs = new Array();
  this.valattribs = new Array();
  
  this.areVariablesSet = false;
}

function _deleteCursor() {
  try {
    var nd;
    nd = this.selectedCursorX;
    var newArray = Array();
    var j = 0;
    for (var i = 0; i < this.cursorArray.length; i++) {
      if (this.cursorArray[i] != nd) {
        newArray[j++] = this.cursorArray[i];
      }
    }
    nd.parentNode.removeChild(nd);
    this.cursorMode = false;
      this.cursorArray = newArray;
  }
  catch (e) {}
  if (this.cursorArray.length < 1) { //M.L. - changed from "this.cursorArray.length == 0", for some reason didn't work.
     if (!isAdhoc) {
		if ((!this.zoomed) && (eval("vDefaultIsUpdating" + this.wpq))) { //M.L. - added check for extra condition: eval("vDefaultIsUpdating" + this.wpq, to see if Autoupdate mode is checked
			eval("undoZoom" + this.wpq + "('false')");
		}
	}
	else {
		if (!this.zoomed) { //M.L. - keep the same code for Ad hoc trend
			eval("undoZoom" + this.wpq + "('false')");
		}
	}
  }
}
SVGObject.prototype.DeleteCursor = _deleteCursor;

function _showAnnotationOff() {
  try {
    if (this.tipTimer == -1) { return; }
    clearTimeout(this.tipTimer);
    this.tipTimer = -1;
    this.svgdoc.getElementById("annotation").setAttribute("style","display:none");
    }
  catch (e) { }
}
SVGObject.prototype.ShowAnnotationOff = _showAnnotationOff;


function _showAnnotationOn(evt,txt,w,h) {
   this.evtX = evt.clientX;
   this.evtY = evt.clientY;
   this.txt = txt;
   this.aW = w;
   this.aH = h;
   if(txt.indexOf('trendTT') == -1) {
    this.lastClientX = 0;
    this.lastClientY = 0;  
   }
  
   this.tipTimer = setTimeout("showAnnotationTT" + this.wpq + "()",500);

   if (!this.areVariablesSet) {
    this.InitSVGVariables();
   }
}
SVGObject.prototype.ShowAnnotationOn = _showAnnotationOn;

function _showAnnotationTT() {
  xdiff = Math.abs(parseInt(this.evtX) - parseInt(this.lastClientX));
  ydiff = Math.abs(parseInt(this.evtY) - parseInt(this.lastClientY));
  if(this.lastClientX != 0 && this.lastClientY !=0)
    if ((xdiff > 10) || (ydiff > 10)) {
      return;
    }
  nd = this.svgdoc.getElementById("annotationRect");
  nd.setAttribute("width",this.aW);
  nd.setAttribute("height",this.aH);
  nd = this.svgdoc.getElementById("annotation");
  if(this.txt.indexOf('rtGraphicTT') == -1) // trend webpart tooltip
  {
  switch (this.rotation)
  {
    case "90":
    case "-90":
    nd.setAttribute("transform","translate(" + parseFloat((this.evtX - this.aW) - 8) + "," + parseFloat(this.evtY)  + ")");
    break;
    default:
    if ((this.evtX - this.aW) > 0) {
      nd.setAttribute("transform","translate(" + parseFloat(this.evtX - this.aW) + "," + parseFloat(this.clientY + 8)  + ")");      
    }
    else {
      nd.setAttribute("transform","translate(" + this.evtX + "," + parseFloat(this.clientY + 8)  + ")");
    }
    break;
  }
  }
else //rtGraphic tool tip
{
  var x = this.evtX;
  var y = this.evtY;
  this.vb_Orientation = ((this.wp_H / this.wp_W) > (this.vb_H / this.vb_W));
  
  if(this.vb_Orientation) // true: webpart width = svg width
  {
    x = (this.evtX) / this.vb_Ratio;
    y = (this.evtY - (this.wp_H - this.vb_H * this.vb_Ratio) / 2 ) / this.vb_Ratio;
  }
  else // false: webpart height = svg height
  {
    x = (this.evtX - (this.wp_W - this.vb_W * this.vb_Ratio) / 2) / this.vb_Ratio;
    y = (this.evtY) / this.vb_Ratio;
  }
  if((y + this.aH) > this.vb_H) // below of bottom border
    y = (this.vb_H - this.aH) > 0 ? (this.vb_H - this.aH) : 0;
  if((x + this.aW) > this.vb_W) // out of right border
    x = (this.vb_W - this.aW) > 0 ? (this.vb_W - this.aW) : 0;
  
    nd.setAttribute("transform","translate(" + parseInt(x).toString() + "," + parseInt(y).toString()  + ")");
}
  nd.setAttribute("style","display:block");
  nd = this.svgdoc.getElementById("annotationText");  
  if (nd != null) {
    nd.parentNode.removeChild(nd);
  }
  nd = this.svgdoc.getElementById("clckForDtls");  
  if (nd != null) {
    nd.parentNode.removeChild(nd);
  }
  var docFrag = this.svgScript.parseXML("<root>" + this.txt + "</root>",this.svgdoc);
  nd = this.svgdoc.getElementById("annotation");
  var k = docFrag.childNodes.item(0).childNodes.length;
  for (; k != 0 ;k--) {
    nd.appendChild(docFrag.childNodes.item(0).childNodes.item(0));
  }
  this.tipTimer = setTimeout("showAnnotationOff" + this.wpq + "()",5000);
}
SVGObject.prototype.ShowAnnotationTT = _showAnnotationTT;

function _showAnnotation(txt) {
  this.ShowAnnotationOff();
  clearTimeout(this.tipTimer);
  this.tipTimer = -1;
  try {
    txt = escapeProperly(txt); //added try-catch here because of error from Adhoc trend Url. M.L.
  }
  catch (e) {}
  var url = "annotations.aspx?lcid=" + rtLocale + "&langID=" + GetSPLangID() + "&a=" + txt;
  if (!isAdhoc) {
    url = "/" + webServicesVDIR + "/annotations.aspx?lcid=" + rtLocale + "&langID=" + GetSPLangID() + "&a=" + txt;
  }

    try
    {
        window.showModalDialog(url,window,"dialogHeight:130px; dialogWidth: 700px;status:no;help:no;resizable:yes;unadorned:yes;scroll:yes", false);
	}
	catch(ex)
	{
	    // If the IE7 pop-up blocker is enabled, we might get an access denied error
	    alert(ex.message);
	}
}
SVGObject.prototype.ShowAnnotation = _showAnnotation;

function _undoZoomMode() {
  this.zoomed = false;
  this.svgdoc.getElementById("hourglass").setAttribute("style","display:block");
  this.svgdoc.getElementById("hgAnim").beginElement();
  this.hourglass = setInterval("rotate" + this.wpq + "()",25000);
  eval("undoZoom" + this.wpq + "('true')");

}
SVGObject.prototype.UndoZoomMode = _undoZoomMode;

function _removeAllCursors() {
  try {
    var svg = this.svgdoc.getElementById("Trend_Graphical");
    for (var i = 0; i < this.cursorArray.length; i++) {
      try {
        svg.removeChild(this.cursorArray[i]);
      }
      catch (e) { }
    }
    this.cursorArray.length = 0;
    this.cursorMode = false;
  }
  catch (e) {}
  if (!this.zoomed) {
	if (!isAdhoc) //M.L. - for the trend, do extra check; for Ad hoc do the old check:
    {
		if ((!this.zoomed) && (this.cursorArray.length < 1) && (eval("vDefaultIsUpdating" + this.wpq))) { //M.L. added extra condition (eval("vDefaultIsUpdating" + this.wpq) to check if AutoUpdate is unchecked
			eval("undoZoom" + this.wpq + "('false')");
		}
	}
	else {
		if ((!this.zoomed) && (this.cursorArray.length < 1)) { //M.L. - for Ad hoc trend, keep the old code
			eval("undoZoom" + this.wpq + "('false')");
		}
    }
  }
}
SVGObject.prototype.RemoveAllCursors = _removeAllCursors;

var wasHandled = false;
function _selectCursor(evt) {
  try {
    if (this.selectedCursorX != null) {
      this.selectedCursorX.childNodes.item(0).childNodes.item(1).setAttribute("stroke-width","1");
    }
    
    this.selectedCursorX = this.svgdoc.getElementById("Trend_Graphical").removeChild(evt.target.parentNode.parentNode);
    this.selectedCursorX.childNodes.item(0).childNodes.item(1).setAttribute("stroke-width","2");
    this.svgdoc.getElementById("Trend_Graphical").appendChild(this.selectedCursorX);
    
    if (((evt.clientY > (this.clientH + this.upperLeftY)) ||
         (evt.clientY < this.upperLeftY)) &&
         (evt.button == 2)) {
      return;
    }

    if (evt.button != 2) {
      this.cursorMode = true;  
      this.rtClickX = evt.clientX; // - this.clientX;
      this.rtClickY = evt.clientY;
    }
    nd = this.svgdoc.getElementById("Remove");
    nd.setAttribute("enabled","no");
    if (evt.button == 2) {
      nd = this.svgdoc.getElementById("Remove");
      nd.setAttribute("enabled","yes");
      nd = this.svgdoc.getElementById("RemoveAll");
      nd.setAttribute("enabled","yes");
      evt.cancelBubble = true;
      evt.returnValue = false;
      wasHandled = true;
    }
  }
  catch (e) {}
  this.svgScript.updateMenu();
  return false;
}
SVGObject.prototype.SelectCursor = _selectCursor;

function _doCursor2(x) {
  var valrect;
  var valrectrect;
  var w;
  try {
    var oor1;
    var oor2;
    switch (this.rotation) {
      case "90":
        x = this.rtClickY;
        oor1 = this.clientY + 1;
        oor2 = this.clientH + this.clientY;
        break;
      case "-90":
        x = this.rtClickY;
        oor1 = this.clientY + 3;
        oor2 = this.clientH + this.clientY + 0;
        break;
      default:
        oor1 = this.clientX + 1;
        oor2 = this.clientW + this.clientX;
        break;
    }
    
    if ((x >= oor1) && (x <= oor2)) {
      x1 = parseInt(x) - this.clientX;
      try {
        valrect = this.selectedCursorX.firstChild;
        valrectchildren = valrect.childNodes;
        for (var i=2; i < valrectchildren.length; i++) {
          try {
            valrectchildren.item(i).setAttribute("display","none");
          }
          catch (e) {}
        }
        valrectrect = valrect.firstChild.nextSibling;
        w = valrectrect.getAttribute("width");
      }
      catch (e3) {}

//      if ((this.rtClickY > (this.clientH + this.upperLeftY)) ||
//          (this.rtClickY < this.upperLeftY)) {
//      if ((this.rtClickY > (this.containerH - 3)) ||
//          (this.rtClickY < this.upperLeftY)) {
//          return;
//      }
      
      try {
        cline = this.selectedCursorX.firstChild.nextSibling;
        this.selectedCursorX.setAttribute("display","block");

        rh = parseFloat(valrectrect.getAttribute("height"));
        switch (this.rotation) {
        case "90":
          cline.setAttribute('transform','translate(0,' +  (this.rtClickY - 40) + ')');
          valrect.setAttribute('transform','translate(' + (parseFloat(this.clientW + this.clientX) - parseFloat(w)) + ',' +  
           parseFloat(this.rtClickY - (rh / 2)) + ')');
          this.realx = (parseFloat(this.rtClickY - this.upperLeftY) * this.secsPerPixel) + this.startTime;
          break;
        case "-90":
          cline.setAttribute('transform','translate(0,' +  (this.rtClickY - 40) + ')');
          valrect.setAttribute('transform','translate(' + (parseFloat(this.clientW + this.clientX) - parseFloat(w)) + ',' +  
           parseFloat(this.rtClickY - (rh / 2)) + ')');
          this.realx = this.endTime - ((parseFloat(this.rtClickY) - parseFloat(this.clientY)) * this.secsPerPixel);
          break;
        default:
          cline.setAttribute('transform','translate(' + x + ',0)');
          valrect.setAttribute('transform','translate(' + ( parseInt(x) - ( parseInt(w) / 2)) + ',0)');
            this.realx = (x1 * this.secsPerPixel) + this.startTime;
          break;
        }
      }
      catch (e1) {}
    
      try {
      tmrecttxt = cline.firstChild.nextSibling.nextSibling;
      realTimeStr = this.ConvertTime(this.realx);
      if (realTimeStr == "") {
        this.DeleteCursor();
        this.cursorMode = false;
        return;
      }
      switch (this.rotation) {
        case "90":
        case "-90":
          realTimeArray = realTimeStr.split(' ');
          tmrecttxt.firstChild.nodeValue = realTimeArray[0];
          tmrecttxt =tmrecttxt.nextSibling;
          if (realTimeArray.length == 3) {
            tmrecttxt.firstChild.nodeValue = realTimeArray[1] + realTimeArray[2];          
          }
          else {
            tmrecttxt.firstChild.nodeValue = realTimeArray[1];          
          }
          break
        default:
          tmrecttxt.firstChild.nodeValue = realTimeStr;
      }
    }
    catch (e2) {}
  }
  else {
      this.DeleteCursor();
      this.cursorMode = false;
    }
  }
  catch (e) {}
}
SVGObject.prototype.DoCursor = _doCursor2;

function _adjustCursor(xClick) {
  var valrectX;
  var evtclientX;
  
  try {
    this.TooltipOff();
    valrect = this.selectedCursorX.firstChild;
    cline = this.selectedCursorX.firstChild.nextSibling;
    valrectchildren = valrect.childNodes;
    for (var i=1; i < valrectchildren.length; i++) {
       try {
          valrectchildren.item(i).setAttribute("display","block");
       }
       catch (e) {}
    }
    valrectrect = valrect.firstChild.nextSibling;
    cline = this.selectedCursorX.firstChild.nextSibling;
    ln = valrect.getElementsByTagName("text");
    switch (this.rotation) {
      case "90":
        evtclientX = this.rtClickY - this.clientY;
        this.realx = parseFloat(this.startTime) + (parseFloat(evtclientX) * parseFloat(this.secsPerPixel));
        break;
      case "-90":
        evtclientX = this.clientH - (this.rtClickY - this.clientY) + 3; // + 16;
        this.realx = parseFloat(this.startTime) + (parseFloat(evtclientX) * parseFloat(this.secsPerPixel));
        break;
      default:
        this.realx = (parseFloat((xClick - this.clientX)) * parseFloat(this.secsPerPixel)) + parseFloat(this.startTime);
        evtclientX = (xClick - this.clientX);
        break;
    }


    if ((this.rtClickY > (this.clientH + this.upperLeftY)) ||
        (this.rtClickY < this.upperLeftY)) {
    }

    w = this.ShowCursorFinalX(evtclientX,ln);
    w += 10;
    if (w < 0) {
    this.selectedCursorX.setAttribute("style","display:none");
    }

    valrect = this.selectedCursorX.firstChild;
    valrectrect = valrect.firstChild.nextSibling;
    rh = parseFloat(valrectrect.getAttribute("height"));
    try {
      switch (this.rotation) {
        case "90":
          valrectX = parseFloat(this.clientW + this.clientX) - parseFloat(w + 10);
          valrect.setAttribute('transform','translate(' + 
          valrectX + ',' +  parseFloat(this.rtClickY - (rh / 2)) + ')');
          break;
        case "-90":
          valrectX = parseFloat(this.clientW + this.clientX) - parseFloat(w + 10);
          valrect.setAttribute('transform','translate(' + 
          valrectX + ',' +  parseFloat(this.rtClickY - (rh / 2)) + ')');          
          break;
        default:
          valrectX = parseInt(xClick) - ( parseInt(w) / 2) - 4;
          valrect.setAttribute('transform','translate(' + valrectX + ',2)');
          break;
      }
       valrectrect.setAttribute("width",parseFloat(w) + parseFloat(10));
       tmrect = this.svgdoc.getElementById("tmrect");
     switch (this.rotation) {
        case "90":
          cline.firstChild.setAttribute
           ("d",
            "M " + tmrect.getAttribute("width") + " 40 " +
            "L " + valrectX + " 40");
          break;
        case "-90":
          cline.firstChild.setAttribute
           ("d",
            "M " + tmrect.getAttribute("width") + " 40 " +
            "L " + valrectX + " 40");
          break;
     }
    }
    catch (e1) {}

    this.cursorMode = false;
    rt = this.svgdoc.getElementById("root");
    rt.setAttribute ("onmousedown","");
  rt.setAttribute ("onmouseup","");
  }
  catch (e) {}
}
SVGObject.prototype.AdjustCursor = _adjustCursor;

function _drawCursor() {
  try {
    if ((this.clientH < 126) || (this.clientW < 51))
    {
     return;
    }
    rt = this.svgdoc.getElementById("root");
    rt.setAttribute ("onmousedown","evt.preventDefault()");
    eval("stopUpdates" + this.wpq + "()");
    crsr = this.svgdoc.getElementById("crsrDef");
    permCrsr = crsr.cloneNode(true);
    permCrsr.setAttribute("id","permcrsr" + this.rtClickX);
    svg = this.svgdoc.getElementById("Trend_Graphical");
    svg.appendChild(permCrsr);
    permCrsr.setAttribute("style","display:block");
    
    
    this.cursorMode = true;
    this.cursorArray[this.cursorArray.length] = permCrsr;
    if (this.selectedCursorX != null) {
      this.selectedCursorX.childNodes.item(0).childNodes.item(1).setAttribute("stroke-width","1");
    }
    this.selectedCursorX = permCrsr;
    this.selectedCursorX.childNodes.item(0).childNodes.item(1).setAttribute("stroke-width","2");
    this.DoCursor(this.rtClickX);
    this.AdjustCursor(this.rtClickX);
  }
  catch (e) {}
}
SVGObject.prototype.DrawCursor = _drawCursor;

function _mouseDown(evt) {
  
  if (!this.areVariablesSet) {
    this.InitSVGVariables();
  }
  
  if (wasHandled) {
    wasHandled = false;
    return;
  }
  
  var evtclientY;
  var evtclientX;
  
  try {
    if (evt.button == 2) {
		//21422 - remove tooltip if one exists when user requests context menu
		if (this.tipTimerOff != 0) {
			clearTimeout(this.tipTimerOff);
			this.TooltipOff();
		}
	}	    
    if ( ((this.rotation == 0) && ((this.clientH < 126) || (this.clientW < 51)) ) ||
         ((this.rotation != 0) && ((this.clientH < 51) || (this.clientW < 175)) ) )
    {
      if (evt.button == 2) 
      {
        nd = this.svgdoc.getElementById("AddCursor");
        nd.setAttribute("enabled","no");
        nd = this.svgdoc.getElementById("toggleTips");
        nd.setAttribute("checked","no");
        this.svgScript.updateMenu();
      }
       return;
    }
    nd = this.svgdoc.getElementById("Remove");
    nd.setAttribute("enabled","no");
    nd = this.svgdoc.getElementById("RemoveAll");
    nd.setAttribute("enabled","no");
    if ((evt.clientX > (this.clientW + this.upperLeftX)) || 
        (evt.clientX < this.clientX) || 
        (evt.clientY < this.clientY) ||
        (evt.clientY > (this.clientY + this.clientH))) {
       nd = this.svgdoc.getElementById("AddCursor");
      nd.setAttribute("enabled","no");    
    }
    else {
       nd = this.svgdoc.getElementById("AddCursor");
      nd.setAttribute("enabled","yes");    
    }
      switch (this.rotation) {
       case "90":
           evtclientY = parseInt((parseFloat(this.clientH) - parseFloat(evt.clientX - this.upperLeftX)) + parseFloat(this.upperLeftX));
           evtclientX = parseInt(parseFloat(evt.clientY ) - parseFloat(this.upperLeftY));
           this.rtClickY = evt.clientY; // - this.upperLeftY;
           this.rtClickX = evt.clientX; // - this.upperLeftY;
         break;
       case "-90":
           evtclientY = parseFloat(evt.clientX - this.upperLeftX);
           evtclientX = parseInt(parseFloat(evt.clientY ) - parseFloat(this.upperLeftY));
           this.rtClickY = evt.clientY;
           this.rtClickX = ((this.containerH - evt.clientY) - this.upperLeftY);
         break;
       default:
           evtclientY = evt.clientY;
           evtclientX = evt.clientX;
           this.rtClickX = evt.clientX;
           this.rtClickY = evt.clientY;
      }
  
  if ((evt.button == 2) &&
        ((!this.cursorMode) &&
        (!this.boxstart == 1))) {
    if (this.cursorArray.length > 0) {
      nd = this.svgdoc.getElementById("RemoveAll");
      nd.setAttribute("enabled","yes");
    }

    if (this.zoomed) {
      nd = this.svgdoc.getElementById("UndoZoom");
      nd.setAttribute("enabled","yes");
    }
    else {
      nd = this.svgdoc.getElementById("UndoZoom");
      nd.setAttribute("enabled","no");
    }
    this.svgScript.updateMenu();
    return;
  }
  if ((evt.button == 2) &&
      ((this.cursorMode) ||
      (this.boxstart == 1))) {
      return;
  }

  if (this.cursorMode) {
      return;
  }

  if (this.boxstart == 1) {
      return;
  }

  switch (this.rotation) {
   case "90":
     if ( (evt.clientX < parseFloat(this.clientX + this.clientW)) &&
          (evt.clientX > this.clientX) &&
          (evt.clientY > this.clientY) &&
          (evt.clientY < parseFloat(this.clientY + 12)) ) {
      this.DrawCursor();
      this.cursorMode = true;
      return;
     }
     break;
   case "-90":
     if ( (evt.clientX < parseFloat(this.clientX + this.clientW)) &&
          (evt.clientX > this.clientX) &&
          (evt.clientY > parseFloat(this.clientH + this.clientY) - 12) &&
          (evt.clientY < parseFloat(this.clientH + this.clientY) + 16) ) {
      this.DrawCursor();
      this.cursorMode = true;
      return;
     }
     break;
   default:
      if ( (evt.clientX < (parseFloat(this.clientX) + parseInt(12))) &&
           (evt.clientY > parseFloat(this.clientY)) && (evt.clientY < (parseFloat(this.clientY + this.clientH))) )
      {
        this.DrawCursor();
        this.cursorMode = true;
        return;
      }
  }
  
  
  if (evt.clientX > (this.clientX + 1)) {
    if ((evt.clientX > this.upperLeftX) &&
        (evt.clientX < this.lowerRightX) &&
        (evt.clientY >= this.upperLeftY) &&
        (evt.clientY <= this.lowerRightY)) {
      eval("stopUpdates" + this.wpq + "()");
      zm = this.svgdoc.getElementById("zm");
      this.startx = parseFloat(evt.clientX) ;
      this.starty = parseFloat(evt.clientY) ;
      zm.setAttribute('x',evt.clientX );
      zm.setAttribute('y',evt.clientY );
      zm.setAttribute('style','display:block');
      this.boxstart = 1;
    }
  }
  }
  catch (e) {}
}
SVGObject.prototype.MouseDown = _mouseDown;

function _tooltipstatus(evt) {
  try {
    if (!this.areVariablesSet) {
      this.InitSVGVariables();
    }
  
    if ((this.boxstart == 1) || (this.cursorMode == true)) return;
    
    //22305 - ignore mouseover if tooltip visible.
    if (this.tipTimerOff != 0) {
      return;
    }
    
    this.TooltipOff();
    if ((this.clientH < 126) || (this.clientW < 51))
    {
      return;
    }

    //22305 - ignore mouseover if tooltips disabled.
    if (this.svgdoc.getElementById("toggleTips").getAttribute("checked") == "no") {
      return;
    }
    
    //22062 - adjust time for servers time zone
    var biasRule = 0;
    for (var i=0; i < this.tzRules.length; i++) {
      var tzRuleStart = this.tzRules.item(i).getElementsByTagName("start");
      if (parseFloat(tzRuleStart.item(0).firstChild.nodeValue) >= this.realx) {
        break;
      }
      biasRule = i;
    }
    var bias = this.tzRules.item(biasRule).getElementsByTagName("bias");

    tm = formatDateTime((this.statusTime - bias.item(0).firstChild.nodeValue) * 1000);
    this.tipTimerOff = setTimeout("tooltipOff" + this.wpq + "()",2500);
    
    eval("stopUpdates" + this.wpq + "()");

    this.tags.length = 0;
    this.vals.length = 0;
    this.mrkrs.length = 0;
    this.valattribs.length = 0;

    this.vals[this.vals.length] = this.status;
    this.tags[this.tags.length] =  this.annotations.item(this.trace).getAttribute("name");
    this.mrkrs[this.mrkrs.length] = this.annotations.item(this.trace).getAttribute("mrkr");
    
    this.evtY = evt.clientY;
    this.ShowTip(evt.clientX,evt.clientY,tm);
    
  }
  catch (e) {}
}
SVGObject.prototype.Tooltipstatus = _tooltipstatus;

function _processKey(evt) {
  if (this.selectedCursorX == null) {
    return;
  }
  xfrm = this.selectedCursorX.childNodes.item(1).attributes.item(1).value;
  lparenIdx = xfrm.indexOf('(');
  rparenIdx = xfrm.indexOf (')');
  xfrm = xfrm.substring(++lparenIdx,--rparenIdx);
  xfrmCoords = xfrm.split(',');
  
  switch (this.rotation) {
  case "90":
  case "-90":
    if (evt.keyCode == 38) {
      this.DoCursor(--this.rtClickY);
      this.AdjustCursor(this.rtClickY);
    }
    if (evt.keyCode == 40) {
      this.DoCursor(++this.rtClickY);
      this.AdjustCursor(this.rtClickY);
    }
       break;
  default:    
    if (evt.keyCode == 39) {
      this.rtClickX = xfrmCoords[0];
      this.DoCursor(++this.rtClickX);
      this.AdjustCursor(this.rtClickX);
    }
    if (evt.keyCode == 37) {
      this.rtClickX = xfrmCoords[0];
      this.DoCursor(--this.rtClickX);
      this.AdjustCursor(this.rtClickX);
    }
    break;
  }
}
SVGObject.prototype.ProcessKey = _processKey;

function _mouseUp(evt) {
  try {
    if (this.cursorMode == true) {
     switch (this.rotation) {
     case "90":
         this.rtClickX = evt.clientY - this.clientY;
         this.rtClickY = evt.clientY;
       break;
     case "-90":
           this.rtClickY = evt.clientY;
           this.rtClickX = parseFloat(this.clientH - evt.clientY) + 7;
       break;
     default:
         this.rtClickX = evt.clientX;
         this.rtClickY = evt.clientY;
     }
     this.DoCursor(this.rtClickX);
     this.cursorMode = false;
     this.AdjustCursor(this.rtClickX);
     return;
    }
    else {
      if (this.boxstart == 1) {
        zm = this.svgdoc.getElementById("zm");
        this.boxstart = 0;
        zm.setAttribute('style','display:none');
        w =  zm.getAttribute('width');
        h =  zm.getAttribute('height');
        if ( (w < 5) || (h < 5) ) {
          if (!(w > 4) && !(h > 4)) {
            this.boxstart = 0;
            zm.setAttribute('style','display:hidden');
            zm.setAttribute('width',0);
            zm.setAttribute('height',0);
            if (!isAdhoc)
            {
				if ((this.cursorArray.length < 1) && (eval("vDefaultIsUpdating" + this.wpq))) { //M.L. - added extra condition: eval("vDefaultIsUpdating" + this.wpq, to see if Autoupdate mode is checked{
					eval("undoZoom" + this.wpq + "('false')");
				}
			}
			else 
			{
				if (this.cursorArray.length < 1) { //M.L. - keep the old code for Ad hoc trend
					eval("undoZoom" + this.wpq + "('false')");
				}
			}
            return;
         }
        }
        this.TooltipOff();
        switch (this.rotation) {
        case "90":
            //SCR# 22871
            if ((this.starty > evt.clientY) && (parseFloat(this.starty - evt.clientY) < parseFloat(this.clientY))) 
            { 
                xx  = parseFloat(evt.clientY - this.clientY);
            }
            else {
                xx  = parseFloat(this.starty - this.clientY);
            }
            this.DetermineZoomArea
             (evt.clientY,
              evt.clientX,
              this.clientY,
              xx, //parseFloat(this.starty - this.clientY),
              parseFloat(this.startx),
              this.clientW,
              this.clientH,
              this.clientX,
              h,
              w);
          break;
        case "-90":
            //xx  = parseFloat(this.starty - this.clientY);
            //SCR# 22871
            if ((this.starty > evt.clientY) && (parseFloat(this.starty - evt.clientY) < parseFloat(this.clientY))) 
            { 
                xx  = parseFloat(evt.clientY - this.clientY);
            }
            else {
                xx  = parseFloat(this.starty - this.clientY);
            }
            this.DetermineZoomArea
             (evt.clientY,
              evt.clientX,
              this.clientY,
              xx,
              this.startx,
              this.clientW,
              this.clientH,
              this.clientX,
              h,
              w);
          break;
        default:
           //SCR# 22871 - correcting calculation of startX (added extra check when zooming from right-to-left)
           if ((this.startx > evt.clientX) && (parseFloat(this.startx - evt.clientX) < parseFloat(this.clientX)))
           {
             xx = parseFloat(evt.clientX - this.clientX);
           }
           else 
           {
             xx = parseFloat(this.startx - this.clientX);
           }
           this.DetermineZoomArea
             (evt.clientX,
              evt.clientY,
              this.clientX,
              xx,
              this.starty,
              this.clientH,
              this.clientW,
              this.clientY,
              w,
              h);
          break;
        }
        this.zoomed = true;
        zm.setAttribute('x','0');
        zm.setAttribute('y','0');
        zm.setAttribute('width','0');
        zm.setAttribute('height','0');
      }
      rt = this.svgdoc.getElementById("root");
       rt.setAttribute ("onmousedown","");
      rt.setAttribute ("onmouseup","");
    }
  }
  catch (e) {
    if (this.cursorMode) {
      this.selectedCursorX.setAttribute("style","display:none");
      this.cursorMode = false;
      rt = this.svgdoc.getElementById("root");
       rt.setAttribute ("onmousedown","");
      rt.setAttribute ("onmouseup","");
    }
  }
}
SVGObject.prototype.MouseUp = _mouseUp;

function _mouseMove(evt) {
  try {
  
  if ((evt.clientY < 3) || (evt.clientY > (this.containerH - 2))) {
    this.MouseUp(evt);
    return;
  }
  
  switch (this.rotation) {
   case "90":
     evtclientY = parseInt((parseFloat(this.clientH) - parseFloat(evt.clientX - this.upperLeftX)) + parseFloat(this.upperLeftX));
     evtclientX = parseInt(parseFloat(evt.clientY ) - parseFloat(this.upperLeftY));
     break;
   case "-90":
     evtclientY = parseInt((parseFloat(this.clientH) - parseFloat(evt.clientX - this.upperLeftX)) + parseFloat(this.upperLeftX));
     evtclientX = parseInt(parseFloat(evt.clientY ) - parseFloat(this.upperLeftY));
     break;
   default:
     evtclientY = evt.clientY;
     evtclientX = evt.clientX - this.clientX;
     break;
  }
    this.lastClientX = evt.clientX;
    this.lastClientY = evt.clientY;
    if (this.cursorMode) {
      switch (this.rotation) {
       case "90":
           this.rtClickX = evt.clientY - this.upperLeftY;
           this.rtClickY = evt.clientY;
         break;
       case "-90":
           this.rtClickX = ((this.containerH - evt.clientY) - this.upperLeftY);
           this.rtClickY = evt.clientY;
         break;
       default:
          this.rtClickX = evt.clientX;
          this.rtClickY = evt.clientY;
      }
       this.DoCursor(this.rtClickX);
       return;
    }
    if (this.boxstart == 1) {
      if ((evt.clientX > parseFloat(this.upperLeftX + 2)) &&
         (evt.clientX < parseFloat((this.clientW  + this.upperLeftX) - 2)) &&
         (evt.clientY > this.upperLeftY + parseInt(2)) &&
         (evt.clientY < this.lowerRightY)) {
		zm = this.svgdoc.getElementById("zm");
		if (evt.clientX < this.startx) {
		  zm.setAttribute('width',this.startx - evt.clientX);
		  zm.setAttribute('x', evt.clientX);
		}
		else {
		  zm.setAttribute('width',evt.clientX - this.startx );
		}
		if (evt.clientY < this.starty) {
		  zm.setAttribute('height',this.starty - evt.clientY);
		  zm.setAttribute('y', evt.clientY);
		}
		else {
		  zm.setAttribute('height',evt.clientY - this.starty);
		}
	  }
    }
  }
  catch (e) { }
}
SVGObject.prototype.MouseMove = _mouseMove;

function _toolTipOn(evt) {
  // 21197 - suppress interpolated tool tip values for restart markers.
   if (this.notip) {
     this.notip = false;
     return;
   }
   if (this.tipTimer > 0) {
     return;
   }
   if (this.svgdoc.getElementById("toggleTips").getAttribute("checked") == "no") {
     return;
   }
   
   if (this.boxstart == 1) {
     return;
   }
   if (this.tipTimerOff != 0) {
     return;
   }
   this.evtX = evt.clientX;
   this.evtY = evt.clientY;
   
   this.tipTimer = setTimeout("toolTipOnTO" + this.wpq + "()",250);
   if (!this.areVariablesSet) {
     this.InitSVGVariables();
   }
  
}
SVGObject.prototype.ToolTipOn = _toolTipOn;

function _tooltipOff() {
  try {
    if (this.tipTimerOff == 0) { return; }
    if (!isAdhoc) //M.L. for the trend, do extra check
    {
		if ((!this.zoomed) && (this.cursorArray.length < 1) && (eval("vDefaultIsUpdating" + this.wpq))) { //M.L. added extra condition (eval("vDefaultIsUpdating" + this.wpq) to check if AutoUpdate is unchecked
			eval("undoZoom" + this.wpq + "('false')");
		}
	}
	else  //M.L. - for Ad hoc trend, keep the old code
	{
		if ((!this.zoomed) && (this.cursorArray.length < 1)){
			eval("undoZoom" + this.wpq + "('false')");
		}
    }
    clearTimeout(this.tipTimerOff);
    this.tipTimerOff = 0;
    this.svgdoc.getElementById("tGroup").setAttribute("style","display:none");
    this.svgdoc.getElementById("txtGroup").setAttribute("style","display:none");
    this.svgdoc.getElementById("tipTime").setAttribute("style","display:none");
    this.tipGroup.setAttribute("style","display:none");
    for (var j=0; j < this.numTraces; j++) {
      this.svgdoc.getElementById("tip" + j + "Val").parentNode.setAttribute("style","display:none");
    }
  }
  catch (e) { }
}
SVGObject.prototype.TooltipOff = _tooltipOff;


function _initSVGDoc() {
   try
  {
      this.svgdoc.getElementById("hourglass").setAttribute("style","display:block");
      this.svgdoc.getElementById("hgAnim").beginElement();
      this.hourglass = setInterval("rotate" + this.wpq + "()",25000);
  }
  catch (e)
   {
    return;
  }
}
SVGObject.prototype.InitSVGDoc = _initSVGDoc;

var maxInit = 0;
function _initSVGVariables() {
  try {
    this.containerH   = this.svgdoc.getElementById("Trend_Graphical").getAttribute("height");  
    this.containerW   = this.svgdoc.getElementById("Trend_Graphical").getAttribute("width");  
    variables         = this.svgdoc.getElementById("variables");
    nd                = variables.getElementsByTagName("secsPerPixel");
    this.secsPerPixel = parseFloat(nd.item(0).firstChild.nodeValue);
    nd                = variables.getElementsByTagName("startTime");
     this.startTime    = parseFloat(nd.item(0).firstChild.nodeValue);
    nd                = variables.getElementsByTagName("endTime");
     this.endTime      = parseFloat(nd.item(0).firstChild.nodeValue);
    this.perPixels    = variables.getElementsByTagName("valsPerPixel");
    this.minvalsnd    = variables.getElementsByTagName("minval");
     this.maxvalsnd    = variables.getElementsByTagName("maxval");
    this.tzRules      = variables.getElementsByTagName("tzRule");
    this.inverted     = variables.getElementsByTagName("inverted");

    this.upperXs     = variables.getElementsByTagName("upperX");
    this.upperYs     = variables.getElementsByTagName("upperY");
    this.widths      = variables.getElementsByTagName("width");
    this.height       = variables.getElementsByTagName("height");
    this.clientX     = parseInt(this.upperXs.item(0).firstChild.nodeValue);
    this.clientY     = parseInt(this.upperYs.item(0).firstChild.nodeValue);
    this.orientation = variables.getElementsByTagName("orientation").item(0).firstChild.nodeValue;
    this.rotation    = variables.getElementsByTagName("rotation").item(0).firstChild.nodeValue;
    this.upperLeftX  = parseInt(this.clientX);
    this.upperLeftY  = parseInt(this.clientY);

    this.clientH     = parseInt(this.height.item(0).firstChild.nodeValue);
    this.lowerRightY = parseInt(this.clientH) + parseInt(this.clientY);

    this.clientW     = parseInt(this.widths.item(0).firstChild.nodeValue);
    this.clientX2    = parseInt(this.clientX) + parseInt(this.clientW);
    this.lowerRightX = parseInt(this.clientW) + parseInt(this.clientX);
  
    this.svgdoc.getElementById("RectElement").setAttribute("to",this.clientW);
    this.annotations = this.svgdoc.getElementsByTagName("annos");
    if (this.annotations != null) {
      this.numTraces    = this.annotations.length;
    }
    this.tipGroup    = this.svgdoc.getElementById("tipGroup");
    this.tipText     = this.svgdoc.getElementById("tipText");
    this.tipTime     = this.svgdoc.getElementById("tipTime");
    this.tipRect     = this.svgdoc.getElementById("tipRect");
    this.nowline     = this.svgdoc.getElementsByTagName("nowline").item(0).firstChild.nodeValue;
  }
  catch (e) { 
    setTimeout("initSVGVariables" + this.wpq + "()",1);
    return;
  }

  this.areVariablesSet = true;

}
SVGObject.prototype.InitSVGVariables = _initSVGVariables;

function _setTime(evtclientX) {
  try {
    if (evtclientX >= 0) {
      this.realx = (evtclientX * this.secsPerPixel) + this.startTime;
        this.segs = this.indxs[evtclientX].split(",");
    }
    else {
      this.realx = 0;
    }
  }
  catch (e) {  }
}
SVGObject.prototype.SetTime = _setTime;


function _toolTipTime() {
  var biasRule = 0;
  for (var i=0; i < this.tzRules.length; i++) {
    var tzRuleStart = this.tzRules.item(i).getElementsByTagName("start");
    if (parseFloat(tzRuleStart.item(0).firstChild.nodeValue) >= this.realx) {
      break;
    }
    biasRule = i;
  }
  var bias = this.tzRules.item(biasRule).getElementsByTagName("bias");
  //21054 - adjust time for time differential
  //23212 - time diff needs to be subtracted. pitime1 already has the time diff factored in.
  //       the browser needs the raw data time
  return formatDateTime(((this.realx - bias.item(0).firstChild.nodeValue - parseFloat(this.delta))) * 1000);
}
SVGObject.prototype.ToolTipTime = _toolTipTime;

function _convertTime(x) {
  var biasRule = 0;
  try {
  for (var i=0; i < this.tzRules.length; i++) {
    var tzRuleStart = this.tzRules.item(i).getElementsByTagName("start");
    if (parseFloat(tzRuleStart.item(0).firstChild.nodeValue) >= x) {
      break;
    }
    biasRule = i;
  }
  var bias = this.tzRules.item(biasRule).getElementsByTagName("bias");
  return formatDateTime((x - bias.item(0).firstChild.nodeValue) * 1000);
  }
  catch (e) {
	return "";  
  }
}
SVGObject.prototype.ConvertTime = _convertTime;

function _toggleTips() {
  nd = this.svgdoc.getElementById("toggleTips");
  if (nd.getAttribute("checked") == "yes")
  {
    nd.setAttribute("checked","no");
  }
  else
  {
    nd.setAttribute("checked","yes");
  }
  this.svgScript.updateMenu();
}
SVGObject.prototype.ToggleTips = _toggleTips;

function log(x,lg)
{
  return Math.log(x)/Math.log(lg)
}


var minVal;
var maxVal;
var valsPerPixel;
var minvals = "";
var maxvals = "";
var startYPixel;
var endYPixel;

function _calcZoomMinMax(clientH,i) {
  var isLog = this.annotations.item(i).getAttribute("log");
  var pow = this.annotations.item(i).getAttribute("pow");
  var vpp = this.annotations.item(i).getAttribute("vpp");
  var min = this.annotations.item(i).getAttribute("min");
  var vppx = Math.abs((maxVal - minVal)) / this.clientH;
  var vppxx = Math.abs(log(maxVal,10) - log(minVal,10)) / this.clientH;
  
  if (this.rotation != "0") {
    this.CalcZoomMinMaxVert(clientH,i);
    return;
  }
  var invrt = false;
  if (this.inverted.item(i) != null) {
    if (this.inverted.item(i).firstChild.nodeValue != "0") {
      invrt = true;
    }
  }
  if (!invrt) {
    if (endYPixel > (clientH * .9)) {
      if (isLog == "1") {
        minvals += minVal;
      }
      else {
        minvals += minVal;
      }
    }
    else {
      if (isLog == "1") {
        var maxlog = log(parseFloat(maxVal),10);
        if (this.zoomed) {
          var maxlog = log(parseFloat(maxVal),10);
          minvals += Math.pow(10,parseFloat(maxlog) - (parseFloat(endYPixel) * parseFloat(vppxx)))
        }
        else {
         minvals += Math.pow(10,parseFloat(maxlog) - (parseFloat(endYPixel) * parseFloat(vppxx)));
        }
      }
      else {
        minvals += parseFloat(maxVal) - (endYPixel * valsPerPixel) ;
      }
    }
    if (startYPixel > (clientH * .1)) {
      if (isLog == "1") {
        var maxlog = log(parseFloat(maxVal),10);
        if (this.zoomed) {
          var maxlog = log(parseFloat(maxVal),10);
          maxvals += Math.pow(10,parseFloat(maxlog) - (parseFloat(startYPixel) * parseFloat(vppxx)))
        }
        else {
          maxvals += Math.pow(10,parseFloat(maxlog) - (parseFloat(startYPixel) * parseFloat(vppxx)));
        }
      }
      else {
        maxvals += parseFloat(maxVal) - ( parseFloat(startYPixel) * parseFloat(valsPerPixel) );
      }
    }
    else {
      if (isLog == "1") {
        maxvals += maxVal;
      }
      else {
        maxvals += maxVal;
      }
    }
  }
  else {

    if (startYPixel > (clientH * .1)) {
      if (isLog == "1") {
        if (this.zoomed) {
          var maxlog = log(parseFloat(maxVal),10);
          minvals += Math.pow(10,parseFloat(maxlog) + (parseFloat(startYPixel) * parseFloat(vppxx)))
        }
        else {
          var maxlog = log(parseFloat(maxVal),10);
          minvals += Math.pow(10,parseFloat(maxlog) + (parseFloat(startYPixel) * parseFloat(vppxx)))
        }
      }
      else {
        minvals += parseFloat(maxVal) + ( parseFloat(startYPixel) * parseFloat(valsPerPixel) );
      }
    }
    else {
      if (isLog == "1") {
        minvals += maxVal;
      }
      else {
        minvals += maxVal;
      }
    }

    if (endYPixel > (clientH * .9)) {
      if (isLog == "1") {
       maxvals += minVal;
      }
      else {
       maxvals += minVal;
      }
    }
    else {
      if (isLog == "1") {
        if (this.zoomed) {
          var maxlog = log(parseFloat(maxVal),10);
          maxvals += Math.pow(10,parseFloat(maxlog) + (parseFloat(endYPixel) * parseFloat(vppxx)))
        }
        else {
          var maxlog = log(parseFloat(maxVal),10);
          maxvals += Math.pow(10,parseFloat(maxlog) + (parseFloat(endYPixel) * parseFloat(vppxx)))
        }
      }
      else {
       maxvals += parseFloat(maxVal) + (endYPixel * valsPerPixel);
      }
    }
  }
}
SVGObject.prototype.CalcZoomMinMax = _calcZoomMinMax;
function _calcZoomMinMaxVert(clientH,i) {
  var isLog = this.annotations.item(i).getAttribute("log");
  var pow = this.annotations.item(i).getAttribute("pow");
  var vpp = this.annotations.item(i).getAttribute("vpp");
  var min = this.annotations.item(i).getAttribute("min");
  var vppxx = Math.abs(log(minVal,10) - log(maxVal,10)) / clientH;
  
  var invrt = false;
  if (this.inverted.item(i) != null) {
    if (this.inverted.item(i).firstChild.nodeValue != "0") {
      invrt = true;
    }
  }
  if (!invrt) {
    if (startYPixel < (clientH * .1)) {
      minvals += minVal;
    }
    else {
      if (isLog == "1") {
        var minlog = log(parseFloat(minVal),10);
        minvals += Math.pow(10,parseFloat(minlog) + (parseFloat(startYPixel) * parseFloat(vppxx)));
      }
      else {
        minvals += parseFloat(minVal) + (startYPixel * valsPerPixel) ;
      }
    }
    if (endYPixel < (clientH * .9)) {
      if (isLog == "1") {
        var minlog = log(parseFloat(minVal),10);
        maxvals += Math.pow(10,parseFloat(minlog) + (parseFloat(endYPixel) * parseFloat(vppxx)));
      }
      else {
        maxvals += parseFloat(minVal) + (parseFloat(endYPixel) * parseFloat(valsPerPixel) );
      }
    }
    else {
      maxvals += maxVal;
    }
  }
  else {
    if (endYPixel < (clientH * .9)) {
      if (isLog == "1") {
        var minlog = log(parseFloat(minVal),10);
        minvals += Math.pow(10,parseFloat(minlog) - (parseFloat(endYPixel) * parseFloat(vppxx)));
      }
      else {
        minvals += parseFloat(minVal) - ( parseFloat(endYPixel) * parseFloat(valsPerPixel) );
      }
    }
    else {
      minvals += maxVal;
    }

    if (startYPixel < (clientH * .1)) {
      maxvals += minVal;
    }
    else {
      if (isLog == "1") {
        var minlog = log(parseFloat(minVal),10);
        maxvals += Math.pow(10,minlog - (parseFloat(startYPixel) * parseFloat(vppxx)));
      }
      else {
        maxvals += parseFloat(minVal) - (startYPixel * valsPerPixel);
      }
    }
  }
}
SVGObject.prototype.CalcZoomMinMaxVert = _calcZoomMinMaxVert;

function _determineZoomArea(evtClientX,evtClientY,clientX,startx,starty,clientH,clientW,clientY,w,h) {
   
   minvals = "";
   maxvals = "";
   for (var i = 0; i < this.numTraces; i++) {
     valsPerPixel = parseFloat(this.annotations.item(i).getAttribute("vpp"));
     minVal = parseFloat(this.annotations.item(i).getAttribute("min"));
     maxVal = parseFloat(this.annotations.item(i).getAttribute("max"));

     if (startx > evtClientX) {
       startx = startx - w;
     }
    
     if (starty < evtClientY) {
       startYPixel = (starty - clientY);
       endYPixel = evtClientY - clientY;
     }
     else {
       endYPixel = parseFloat((starty - clientY));
       startYPixel = endYPixel - h;
     }
        
     if (i == (this.numTraces - 1)) {
       this.CalcZoomMinMax(clientH,i);
     }
     else {
       this.CalcZoomMinMax(clientH,i);
       minvals += ",";
       maxvals += ",";
    }
  }

  switch (this.rotation) {
    case "-90":
      if ( startx < (clientW * .1) ) {
        etime = this.endTime;
      }
      else
      {
        etime = this.endTime - (parseFloat(startx) * this.secsPerPixel);
      }
      if ( (parseFloat(w) + parseFloat(startx))  > (clientW * .9) )
      {
        stime = this.startTime;
      }
      else
      { 
        stime = this.endTime - ((parseFloat(w) + parseFloat(startx)) * this.secsPerPixel);
      }
      break;
    case "90":
      if ( startx < (clientW * .1  ) )
      {
        stime = this.startTime;
      }
      else
      {
        stime = parseFloat((startx * this.secsPerPixel) + parseFloat(this.startTime));
      }
      if ( ( parseFloat(w) + parseFloat(startx) ) > (clientW * .9) )
      {
        etime = this.endTime;
      }
      else
      { 
        etime = ( ( parseFloat(w) + parseFloat(startx) ) * this.secsPerPixel) + this.startTime;
      }
      break;
    default:
      if ( startx < (clientW * .1) )
      {
        stime = this.startTime;
      }
      else
      {
        stime = parseFloat((startx * this.secsPerPixel) + this.startTime);
      }
      if ( ( parseFloat(w) + parseFloat(startx) ) > (clientW * .9) )
      {
        etime = this.endTime;
      }
      else
      { 
        etime = ( ( parseFloat(w) + parseFloat(startx) ) * this.secsPerPixel) + this.startTime;
      }
      break;
  }
  
  if (Math.round(stime) < Math.round(etime)) {
    this.svgdoc.getElementById("hourglass").setAttribute("style","display:block");
    this.svgdoc.getElementById("hgAnim").beginElement();
    this.hourglass = setInterval("rotate" + this.wpq + "()",25000);
  
    eval("zoom" + this.wpq + "('" + Math.round(stime) + "','" + Math.round(etime) + "','" + minvals + "','" + maxvals + "')");
  }
}
SVGObject.prototype.DetermineZoomArea = _determineZoomArea;

function _rotate() {
  this.svgdoc.getElementById("hgAnim").beginElement();
}
SVGObject.prototype.Rotate = _rotate;

function _adhocTrendHG() {
  try {
//    if (this.hourglass == null) {
//      return;
//    }
    if (!this.hourglassOff && (this.hourglass != null)) {
      this.svgdoc.getElementById("hourglass").setAttribute("style","display:none");
      clearTimeout(this.hourglass);
      this.hourglass = null;
      this.hourglassOff = true;
      return;
    }
  }
  catch (e) {
  }
  
  try {
    this.svgdoc.getElementById("hourglass").setAttribute("style","display:block");
    this.svgdoc.getElementById("hgAnim").beginElement();
    this.hourglassOff = false;
    this.hourglass = setInterval("rotate" + this.wpq + "()",25000);
  }
  catch (e) {}
  setTimeout("showAdhocTrend" + this.wpq + "()",1);
}
SVGObject.prototype.AdhocTrendHG = _adhocTrendHG;

var maxUpdate = 0;
function _doUpdate(updXML) {
  try {
     this.svgdoc.getElementById("hourglass").setAttribute("style","display:none");
     clearTimeout(this.hourglass);
//     this.hourglass = null;
     var strt = new Date();
     var docFrag = this.svgScript.parseXML(updXML,this.svgdoc);
     var docFragNodes = docFrag.childNodes;
     for(var n = 0 ; n < docFragNodes.length ; n++ ) {
       id = docFragNodes.item(0).getAttribute("id");
       if (id.length > 0) {
         currentNode = this.svgdoc.getElementById(id);
         if (currentNode != null) {
           prnt = currentNode.parentNode;
           prnt.replaceChild(docFragNodes.item(0),currentNode);
         }
         else {
           this.svgdoc.appendChild(docFragNodes.item(0));
         }
       }
       else {
         this.svgdoc.appendChild(docFragNodes.item(0));
       }
     }          
     var diff = new Date() - strt;
     if (diff > maxUpdate) {
       maxUpdate = diff;
     }
     this.areVariablesSet = false;
     //setTimeout("initSVGVariables" + this.wpq + "()",1);          
  }
  catch (e) {}
}
SVGObject.prototype.DoUpdate = _doUpdate;


function _findPoint(timeNodes, minIdx, maxIdx, midIdx, targetTime) { 
    if (parseInt(midIdx + 1) < timeNodes.length) {
      thisTime = timeNodes.item(midIdx).firstChild.nodeValue;
      nextTime = timeNodes.item(midIdx + 1).firstChild.nodeValue;
    }
    else {
      if (parseInt(midIdx + 1) == timeNodes.length) {
        thisTime = timeNodes.item(midIdx).firstChild.nodeValue;
        nextTime = thisTime;
      }
      else {
        return timeNodes.length - 1;
      }
    }      
    
    if (maxIdx == parseInt(minIdx + 1)) {
      thisTime = timeNodes.item(minIdx).firstChild.nodeValue;
      if (thisTime > targetTime) {
        return -1;
      }
      //21189 - log for highest priority value atttibute
      if ((minIdx > 0) && (thisTime == timeNodes.item(minIdx - 1).firstChild.nodeValue)) {
        if ((minIdx > 1) && (thisTime == timeNodes.item(minIdx - 2).firstChild.nodeValue)) {
		  return minIdx - 2;
		}
		return minIdx - 1;
      }      
      return minIdx;
    }
    
    if ( (parseFloat(thisTime) <= parseFloat(targetTime)) &&
         (parseFloat(nextTime) >= parseFloat(targetTime)) ) {
      //21189 - log for highest priority value atttibute
      if ((midIdx > 0) && (thisTime == timeNodes.item(midIdx - 1).firstChild.nodeValue)) {
        if ((midIdx > 1) && (thisTime == timeNodes.item(midIdx - 2).firstChild.nodeValue)) {
		  return midIdx - 2;
		}
		return midIdx - 1;
      }      
        //22920 - added test for next time equal to target. if it is we wan to use the next point if the
        //  next and previous points are different. 
      if ( (parseFloat(nextTime) == parseFloat(targetTime)) &&
            (nextTime > thisTime) ) {
        return midIdx + 1;
      }
      else {
        return midIdx;
      }
    }
    
    if ( parseFloat(thisTime) > parseFloat(targetTime) ) {
      maxIdx = midIdx;
      midIdx = minIdx + Math.ceil((maxIdx - minIdx) / 2);
    }
    else {
      minIdx = midIdx;
      midIdx = minIdx + Math.ceil((maxIdx - minIdx) / 2);
    }
    return _findPoint(timeNodes, minIdx, maxIdx, midIdx, targetTime);
}
SVGObject.prototype.FindPoint = _findPoint;

function _showCursorFinalX(evtClientX,ln) {
  var val;
  var linNum = 0;
  var maxW = 0;
  var valStr = "";
  var p1Val = "";
  
  for (var i=0; i < this.annotations.length; i++) {
    annos = this.annotations.item(i).getElementsByTagName("X");
    if (annos.length > 0) {

      if (evtClientX > Math.floor(annos.item(annos.length - 1).firstChild.nodeValue)) {
        valStr = annos.item(annos.length - 1).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
        if ((isNaN(valStr)) || (evtClientX > this.nowline)) {
          //21213: enhanced test for showing no data
          //23276 - rounded up the nowline pixel position
          if ((Math.floor(annos.item(annos.length - 1).firstChild.nodeValue) <= Math.ceil(this.nowline)) && (evtClientX > this.nowline)) {
            valStr = "No Data";
          }
          else {
			switch (this.annotations.item(i).getAttribute("type")) {
				case "FLOAT":
				case "INTEGER":
				case "TIMESTAMP":
				  //22089 - only report No Data as a last resort, don't override valid status
				  if (valStr == "NaN") {
				    valStr = "No Data";
				  }
				  else  // 22644 - if valid value exists, show formated value
				  {
      				  try{
      				      if (IsNumeric(valStr)==true)	
      				      {			      
                              var dispDig = this.annotations.item(i).getAttribute("dig");
                              var fmt = this.annotations.item(i).getAttribute("fmt");
                              valStr = formatNumber(valStr,dispDig,this.annotations.item(i).getAttribute("type"),fmt);
                          }
                      }
                      catch(e){
                      }
				  }
				break;
				default:
				break;
			}
          }    
        }
        else {
          var dispDig = this.annotations.item(i).getAttribute("dig");
          var fmt = this.annotations.item(i).getAttribute("fmt");
          switch (this.annotations.item(i).getAttribute("type")) {
            case "FLOAT":
            case "INTEGER":
              valStr = formatNumber(valStr,dispDig,this.annotations.item(i).getAttribute("type"),fmt);
              break;
            case "STRING":
            case "DIGITAL":        
              // 21049 : if value node does not exist set display string to empty string
              try {
                valStr = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
              }
              catch (e) {
				valStr = "";
              }
              if (valStr.length > 35) {
                valStr = valStr.substr(0,35) + "...";
              }
              break;
            case "TIMESTAMP":
              valStr = this.ConvertTime(parseFloat(valStr));
              break;
          }    
        }
        k = annos.length - 1;
      }
      else {
      
        k = this.FindPoint(annos, 0, annos.length, Math.ceil(annos.length / 2), evtClientX);
        
        //23212 - need to skip this trace if no points are found
        if (k == -1) {
          linNum++;
          continue;
        }
        
        // scr 22978 - added logic to ensure that "last" point in trace with duplicate dateTime value 
        // is used for Curor Interpolation
        while (k < annos.length)
        {
            // compare the time with the next node and advance if they are equal, get out if not
            if (k == annos.length-1)
            {
                break;
            }
            var ktime = annos.item(k).firstChild.nodeValue; 
            var ktimex = annos.item(k+1).firstChild.nodeValue;
            if (parseInt(ktime) != parseInt(ktimex))
            {
                break;
            }
            k++;            
        }
        
        if ((annos.length > 1) && (k == 0) && (annos.item(k).firstChild.nodeValue > evtClientX)) {
          k = -1;
        }
        var isStepped = this.annotations.item(i).getAttribute("step");
        var dispDig = this.annotations.item(i).getAttribute("dig");
        var fmt = this.annotations.item(i).getAttribute("fmt");
        if (k == -1) {
          if (evtClientX < annos.item(0).firstChild.nodeValue) {
			valStr = annos.item(0).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
          }
          valStr = "No Data";
        } 
        else {
        
		  //23212 - time diff needs to be subtracted. pitime1 already has the time diff factored in.
          //        the browser needs the raw data time
          var delta = this.annotations.item(i).getAttribute("delta");
          switch (this.annotations.item(i).getAttribute("type")) {
            case "FLOAT":
            case "INTEGER":
              try {
                if (isStepped == 0) {
                  p1Time = parseFloat(annos.item(k).nextSibling.nextSibling.firstChild.nodeValue) + parseFloat(delta);
                  p1Val  = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
                  
                  p2Time = parseFloat(annos.item(k+1).nextSibling.nextSibling.firstChild.nodeValue) + parseFloat(delta);
                  p2Val  = annos.item(k+1).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
                  
                  m = parseFloat(p2Val - p1Val) / parseFloat(p2Time - p1Time);
      
                  if ((m == 0) || isNaN(m) ) {
                    if (isNaN(p1Val)) {
                      valStr = p1Val;
                    }
                    else {
                      valStr = formatNumber
                        (p1Val,
                        dispDig,
                        this.annotations.item(i).getAttribute("type"),
                        fmt);
                    }
                    break;
                  }
      
                  b = parseFloat(p1Val - (m * p1Time));
                  if (this.realx > p2Time) {
                    val = p2Val;
                  }
                  else {
                    val = parseFloat(m * this.realx) + parseFloat(b);
                  }
                  valStr = formatNumber(val,dispDig,this.annotations.item(i).getAttribute("type"),fmt);
                }
                else {
                  p1Val = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
                  if (isNaN(p1Val)) {
                    valStr = p1Val;
                  }
                  else {
                    valStr = formatNumber
                      (annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue,
                      dispDig,
                      this.annotations.item(i).getAttribute("type"),
                      fmt);
                  }          
                }
                if (valStr == "NaN") {
                  valStr = p1Val;
                }
              }
              catch (e) {
                if (isNaN(p1Val)) {
                  valStr = p1Val;
                }
                else {
                  valStr = formatNumber(p1Val,dispDig,this.annotations.item(i).getAttribute("type"),fmt);
                }
              }
              break;
            case "STRING":
            case "DIGITAL":        
              // 21049 : if value node does not exist set display string to empty string
              try {
                valStr = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
              }
              catch (e) {
                valStr = "";
              }
              if (valStr.length > 35) {
                valStr = valStr.substr(0,35) + "...";
              }
              break;
            case "TIMESTAMP":
              try {
                if (isStepped == 0) {
                  p1Time = annos.item(k).nextSibling.nextSibling.firstChild.nodeValue;
                  p1Val  = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
                  p2Time = annos.item(k+1).nextSibling.nextSibling.firstChild.nodeValue;
                  p2Val  = annos.item(k+1).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
                  
                  if (isNaN(p1Val))
                  {
                    valStr = p1Val;
                    break;
                  }
                  else if (isNaN(p2Val))
                  {
                    valStr = this.ConvertTime(p1Val);
                    
                    break;
                  }
                  
                  // otherwise, there are two valid values at the endpoints and we should interpolate
                  
                  m = parseFloat(p2Val - p1Val) / parseFloat(p2Time - p1Time);

                  if ((m == 0) || isNaN(m)) {
                    valStr = this.ConvertTime(p1Val);
                    break;
                  }
                  b = parseFloat(p1Val - (m * p1Time));
                  val = parseFloat(m * this.realx) + parseFloat(b);
                  valStr = this.ConvertTime(parseFloat(val));
                }
                else {
                // stepped - so use the previous value - either a valid utc val or a status string
                  p1val = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
                  if (isNaN(parseFloat(p1val))) {
                    valStr = p1val;
                  }
                  else
                  {
                    valStr = this.ConvertTime(parseFloat(annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue));
                  }
                }
              }
              catch (e) {
                valStr = this.ConvertTime(parseFloat(p1Val));            
              }
              break;
          }
        }
      }

      ln.item(linNum++).firstChild.nodeValue = valStr;          
      if (valStr.length * 6 > maxW) {
        maxW = valStr.length * 6;
      }

      img = ln.item(linNum -1).nextSibling;
      img.setAttribute("xlink:href","");
      if ((k != -1) && (annos.length > 0)) {
         switch (annos.item(k).nextSibling.firstChild.nodeValue){
          case "ANNOTATED":
            img.setAttribute("xlink:href","#ann");
            break;
          case "QUESTIONABLE":
            img.setAttribute("xlink:href","#que");
            break;
          case "SUBSTITUTED":
            img.setAttribute("xlink:href","#sub");
            break;
        }
        img.setAttribute("x",(ln.item(linNum -1).firstChild.nodeValue.length * 6) + 18);
      }
    }
    else {
      valStr = "No Data";
      ln.item(linNum++).firstChild.nodeValue = valStr;
      if (valStr.length * 6 > maxW) {
        maxW = valStr.length * 6;
      }
    }    
  }
  maxW += 16;
  if (maxW < 40) {
    if (maxW == 0) {
       maxW = 48;
    }
    else {
      maxW += 16;
    }
  }
  return maxW;
}
SVGObject.prototype.ShowCursorFinalX = _showCursorFinalX;




function _findToolTipValsX(x,y,min,vpp) {
  var vals = new Array();
  var linNum = 0;
  var valStr = "";
  var nbrVals = 0;
  
  this.tags.length = 0;
  this.vals.length = 0;
  this.mrkrs.length = 0;
  this.valattribs.length = 0;
  
  for (var i=0; i < this.annotations.length; i++) {
    if (this.perPixels.item(i) == null) {
     continue;
    }
    var valsPerPixel = this.perPixels.item(i).firstChild.nodeValue;
    annos = this.annotations.item(i).getElementsByTagName("X");
    if (annos.length > 0) {
        k = this.FindPoint(annos, 0, annos.length, Math.ceil(annos.length / 2), x);
        if (k == -1) {
          continue;
        }
        // scr 22978 - added logic to ensure that "last" point in trace with duplicate dateTime value 
        // is used for Curor Interpolation
        while (k < annos.length)
        {
            // compare the time with the next node and advance if they are equal, get out if not
            if (k == annos.length-1)
            {
                break;
            }
            var ktime = annos.item(k).firstChild.nodeValue; 
            var ktimex = annos.item(k+1).firstChild.nodeValue;
            if (parseInt(ktime) != parseInt(ktimex))
            {
                break;
            }
            k++;            
        }
   
      //22089 - don't show a tooltip value if no y coord value
      if (annos.item(k).nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nodeValue == "NaN") {
        continue;
      }
      

      var isStepped = this.annotations.item(i).getAttribute("step");
      var dispDig = this.annotations.item(i).getAttribute("dig");
      var min = this.annotations.item(i).getAttribute("min");
      var max = this.annotations.item(i).getAttribute("max");
      var inv = this.annotations.item(i).getAttribute("inv");
      var islog = this.annotations.item(i).getAttribute("log");
      var pow = this.annotations.item(i).getAttribute("pow");
      var vpp = this.annotations.item(i).getAttribute("vpp");
      var fmt = this.annotations.item(i).getAttribute("fmt");
      var sclFctr = this.annotations.item(i).getAttribute("sf");
	  //21054 - added to control use of time differential
      var delta = this.annotations.item(i).getAttribute("delta");
      var ht;

      if (this.rotation != 0) {
        ht = this.clientW;
      }
      else {
        ht = this.clientH;
      }
      
      //22978 - this code disables tooltips when mouseover a vertical line of a stepped trace. same
      // behavior as PB.
      if (isStepped != 0) {
        evty = annos.item(k).nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
        evty = parseFloat(evty);
        evty = -evty;
        evtyLo = evty - 1.5;
        evtyHi = evty + 1.5;
        if (!((y > evtyLo) && (y < evtyHi))) {  
            vals[linNum++] = "^" + k;                  
            continue;
        }
      }
      
      switch (this.annotations.item(i).getAttribute("type")) {
        case "FLOAT":        
          if (isStepped == 0) {
            p1Time = annos.item(k).nextSibling.nextSibling.firstChild.nodeValue;
            p1Val  = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
            if (annos.item(k+1) != null) {
              p2Time = annos.item(k+1).nextSibling.nextSibling.firstChild.nodeValue;
              p2Val  = annos.item(k+1).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
              m = parseFloat(p2Val - p1Val) / parseFloat(p2Time - p1Time);
            }
            else {
              m = 0;
            }
            if ((m == 0) || isNaN(m)) {
              val = p1Val;
            }
            else {

              b = parseFloat(p1Val - (parseFloat(m) * parseFloat(p1Time)));
              val = parseFloat(m * this.realx) + parseFloat(b);
            }
            if (inv == 0) {
              if (islog == 0) {
                calcY = (parseFloat(val) - parseFloat(min)) / parseFloat(vpp);
              }
              else {
                calcY = (log(parseFloat(val),10) * parseFloat(ht)) * parseFloat(sclFctr);
                calcY = calcY - ((log(min,10) * parseFloat(ht)) * parseFloat(sclFctr));
                // 21197 position tooltip for invalid value markers on x-axix
                if (isNaN(calcY)) {
					calcY = -3;
                }
              }
            }
            else {
              if (islog == 0) {
                calcY = (min - val) / vpp;
              }
              else {
                calcY = (log(parseFloat(val),10) * parseFloat(ht)) * parseFloat(sclFctr);
                calcY = calcY - ((log(min,10) * parseFloat(ht)) * parseFloat(sclFctr));
                // 21197 position tooltip for invalid value markers on x-axix
                if (isNaN(calcY)) {
					calcY = -3;
                }
              }
            }
            // 21197 - define case where interpolation of values is appropriate.
            if (!islog || (islog && !isNaN(val))) {
              yDiff = (Math.abs(Math.ceil(calcY)) - Math.abs(y));
              if (Math.abs(yDiff) < 5) { 
                valStr = formatNumber(val,dispDig,"FLOAT",fmt);
              }
              else {
                valStr = "";
              }
            }
            // 21197 - if val is a string use it in the tooltip
            if (islog && isNaN(val)) {
              valStr = val;
            }
          }
          else {
            if (this.trace == i) {
              valStr = formatNumber
                 (annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue,
                 dispDig,
                 "FLOAT",
                 fmt);
            }
            else {          
              if (y == -(Math.round(annos.item(k).nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nodeValue))) {
                valStr = formatNumber
                   (annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue,
                   dispDig,
                   "FLOAT",
                   fmt);
              }
              else {
                valStr = "";
              }
            }
            if (valStr == "NaN") {
              valStr = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
            }
          }
          break;
        case "INTEGER":
          if (isStepped == 0) {
            p1Time = annos.item(k).nextSibling.nextSibling.firstChild.nodeValue;
            p1Val  = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
            if (annos.item(k+1) != null) {
              p2Time = annos.item(k+1).nextSibling.nextSibling.firstChild.nodeValue;
              p2Val  = annos.item(k+1).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
              m = parseFloat(p2Val - p1Val) / parseFloat(p2Time - p1Time);
              b = parseFloat(p1Val - (m * p1Time));
            }
            else {
              m = 0;
            }
            if ((m == 0) || isNaN(m)) {
              val = p1Val;
              valStr = formatNumber
                   (p1Val,
                   dispDig,
                   "INTEGER",
                   fmt);
            }
            else {
              val = parseFloat(m * this.realx) + parseFloat(b);
            }
            if (inv == 0) {
              if (islog == 0) {
                calcY = parseFloat((val - min) / vpp);
              }
              else {
                calcY = (log(parseFloat(val),10) * parseFloat(ht)) * parseFloat(sclFctr);
                calcY = calcY - ((log(min,10) * parseFloat(ht)) * parseFloat(sclFctr));
              }
            }
            else {
              if (islog == 0) {
                calcY = parseFloat((min - val) / vpp);
              }
              else {
                calcY = (log(parseFloat(val),10) * parseFloat(ht)) * parseFloat(sclFctr);
                calcY = calcY - ((log(min,10) * parseFloat(ht)) * parseFloat(sclFctr));
              }
            }
            yDiff = Math.abs(Math.ceil(calcY)) - Math.abs(y);
            if (( yDiff <= 2) && (yDiff >= -2)) { 
              valStr = formatNumber
                 (val,
                 dispDig,
                 "INTEGER",
                 fmt);
            }
            else {
              valStr = "";
            }
          }
          else {
            val  = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
            if (this.trace == i) {
              valStr = formatNumber
                 (val,
                 dispDig,
                 "INTEGER",
                 fmt);
            }
            else {          
              if (y == -(Math.round(annos.item(k).nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nodeValue))) {
              valStr = formatNumber
                 (val,
                 dispDig,
                 "INTEGER",
                 fmt);
              }
              else {
                valStr = "";
              }
            }
          
          }
          break;
        case "STRING":
        case "DIGITAL":        
          if (this.trace == i) {
            // 21049 : if value node does not exist set display string to empty string
            try {
              valStr = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
            }
            catch (e) {
              valStr = " ";
            }
          }
          else {
            if (y == -(Math.round(annos.item(k).nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nodeValue))) {
              // 21049 : if value node does not exist set display string to empty string
              try {
                valStr = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;            
              }
              catch (e) {
                valStr = " ";
              }
            }
            else {
              valStr = "";
            }
          }
          break;
        case "TIMESTAMP":
          if (isStepped == 0) {
            p1Time = annos.item(k).nextSibling.nextSibling.firstChild.nodeValue;
            p1Val  = annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
            if (annos.item(k+1) != null) {
              p2Time = annos.item(k+1).nextSibling.nextSibling.firstChild.nodeValue;
              p2Val  = annos.item(k+1).nextSibling.nextSibling.nextSibling.firstChild.nodeValue;
              m = parseFloat(p2Val - p1Val) / parseFloat(p2Time - p1Time);
            }
            else {
              m = 0;
            }
            if ((m == 0) || isNaN(m)) {
              val = p1Val;
            }
            else {
              b = parseFloat(p1Val - (m * p1Time));
              val = parseFloat(m * this.realx) + parseFloat(b);
            }
            
            if (inv == 0) {
              if (islog == 0) {
                calcY = parseFloat((val - min) / vpp);
              }
              else {
                calcY = (log(parseFloat(val),10) * parseFloat(ht)) * parseFloat(sclFctr);
                calcY = calcY - ((log(min,10) * parseFloat(ht)) * parseFloat(sclFctr));
              }
            }
            else {
              if (islog == 0) {
                calcY = parseFloat((min - val) / vpp);
              }
              else {
                calcY = (log(parseFloat(val),10) * parseFloat(ht)) * parseFloat(sclFctr);
                calcY = calcY - ((log(min,10) * parseFloat(ht)) * parseFloat(sclFctr));
              }
            }
            yDiff = Math.abs(Math.ceil(calcY)) - Math.abs(y);
            if (( yDiff < 5) && (yDiff > -5)) { 
              valStr = this.ConvertTime(parseFloat(val));
            }
            else {
              valStr = "";
            }
          }
          else {
            if (this.trace == i) {
              valStr = this.ConvertTime
                (parseFloat(annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue))
            }
            else {          
              if (y == -(Math.round(annos.item(k).nextSibling.nextSibling.nextSibling.nextSibling.firstChild.nodeValue))) {
                valStr = this.ConvertTime
                  (parseFloat(annos.item(k).nextSibling.nextSibling.nextSibling.firstChild.nodeValue))
              }
              else {
                valStr = "";
              }
            }
          }
          break;
      }      
      if (valStr != "") {
        this.vals[this.vals.length] = valStr;
        this.tags[this.tags.length] = annos.item(k).parentNode.getAttribute("name");
        this.mrkrs[this.mrkrs.length] = annos.item(k).parentNode.getAttribute("mrkr");
        this.valattribs[this.valattribs.length] = annos.item(k).nextSibling.firstChild.nodeValue;
        //21054 - added to control the use of time differential. don't use diff if more than one tooltip
        nbrVals++;
        if (nbrVals == 1) {
		  this.delta = delta;
        }
        else {
          this.delta = 0;
        }
      }
      vals[linNum++] = valStr + "^" + k;              
    }
    else {
      vals[linNum++] = "^" + k;                  
    }
  }
  return vals;
}
SVGObject.prototype.FindToolTipValsX = _findToolTipValsX;
function _toolTipOnTOX() {
  var tm;
  var evtclientY;
  var evtclientX;
  var realx;
  var totalW = parseInt(this.svgdoc.getElementById("Trend_Graphical").getAttribute("width"));
  var maxY = this.clientH + this.clientY;

  try {
  
  
    // has mouse moved since a hit was detected. if so dont show tip
    this.tipTimer = -1;
    xdiff = Math.abs(parseInt(this.evtX) - parseInt(this.lastClientX));
    ydiff = Math.abs(parseInt(this.evtY) - parseInt(this.lastClientY));
    if ((xdiff > 4) || (ydiff > 4)) {
      return;
    }
    this.evtX = this.lastClientX;
    
    // if tooltip is still visible ignore hit
    if ((this.tipTimerOff) != 0) { return; }
    
    this.TooltipOff();
    if ( ((this.rotation == 0) && ((this.clientH < 126) || (this.clientW < 51)) ) ||
         ((this.rotation != 0) && ((this.clientH < 51) || (this.clientW < 175)) ) ) {
       return;
    }

  // if doing zoom or cursor, ignore hit
  if ((this.boxstart == 1) || (this.cursorMode == true)) return;
  
  switch (this.rotation) {
   case "90":
     evtclientY = this.evtX - this.upperLeftX;
     evtclientX = parseFloat(this.evtY - this.upperLeftY);
     break;
   case "-90":
     evtclientY = this.evtX - this.upperLeftX;
     evtclientX = this.clientH - parseFloat(this.evtY - this.clientY);
     break;
   default:
     evtclientY = parseFloat(this.clientH + this.clientY) - this.evtY;
     evtclientX = (this.evtX - this.clientX);
     break;
  }
  
    this.SetTime(evtclientX);
  
  // if time is out of range ignore hit
  if (this.realx == 0) { return; }
  
  if (this.lastClientY > this.evtY)  {
    evtclientY -= 1;
  }
  else {
    evtclientY += 1;
  }
  tipGroup = this.svgdoc.getElementById("tipGroup");
  var numTips = 0;
  var tipWidth = 200;
  var addLines = 0;
  var tipNodes = new Array();
  try {
    var valsArray = this.FindToolTipValsX(evtclientX,evtclientY);

    if (this.tags.length == 0) {
      return;
    }
    tm = this.ToolTipTime();
    this.ShowTip(this.evtX,this.evtY,tm);
    this.tipTimerOff = setTimeout("tooltipOff" + this.wpq + "()",2500);
    eval("stopUpdates" + this.wpq + "()");
    return;

    for (var j=0; j < valsArray.length; j++) {
      var vals;
      vals = valsArray[j].split('^');
      nd = this.svgdoc.getElementById("tip" + j + "Val");
      nd.parentNode.setAttribute("style","display:none");
      if ((vals[0] != null) && (vals[0] != "")) {
          nd2 = this.svgdoc.getElementById("tip" + j + "DS");
          if ((40 + (parseInt(nd2.firstChild.nodeValue.length) * 6)) > tipWidth) {
            tipWidth = 40 + (parseInt(nd2.firstChild.nodeValue.length) * 6);
          }
          tipNodes[numTips++] = nd.parentNode;
          nd.parentNode.setAttribute("style","display:block");
          if (vals[0].length > 24) {
            vals[0] = vals[0].substr(0,24) + "...";
            tipWidth += 84;
          }
          nd.firstChild.nodeValue = vals[0];
          
          nd.nextSibling.setAttribute("xlink:href","");

          annos = this.annotations.item(j).getElementsByTagName("S");
          switch (annos.item(vals[1]).firstChild.nodeValue){
              case "ANNOTATED":
                nd.nextSibling.setAttribute("xlink:href","#ann");
                break;
              case "QUESTIONABLE":
                nd.nextSibling.setAttribute("xlink:href","#que");
                break;
              case "SUBSTITUTED":
                nd.nextSibling.setAttribute("xlink:href","#sub");
                break;
          }
          var annoX = parseFloat(nd.getAttribute("x"));
          tipWidth += 12;
          annoX += parseFloat(nd.firstChild.nodeValue.length) * 6;
          nd.nextSibling.setAttribute("x",parseFloat(annoX - 2));  
          
          if ((40 + parseInt(nd.getAttribute("x")) + (parseInt(nd.firstChild.nodeValue.length) * 6)) > tipWidth) {
            tipWidth = 40 + parseInt(nd.getAttribute("x")) + (parseInt(nd.firstChild.nodeValue.length) * 6);
          }
          if (nd.getAttribute("y") != "2.5") {
            addLines++;
          }
        }
      }
  }
  catch (e1) {
    return;
  }

  if (numTips == 0) {
      return;
  }
    
  var scaleFactor = (10 + (numTips * 15)) / 60;
  var lastY = 0;
  strt = -(parseInt(this.evtX) - parseInt(tipWidth) - 40);
  strt2 = parseInt(this.evtX) - parseInt(tipWidth) + 20;
  strt3 = strt2 + (parseInt(tipWidth) / 2) - 15;
  th = 50 + (((numTips + addLines) - 1) * 15);
  for (var x=0; x < numTips; x++) {
      lastY = (parseInt(this.evtY) + 12 + (12 * scaleFactor) + ((x) * 10));
      if ((parseInt(this.evtY) + parseInt(th)) > parseInt(maxY)) {
        lastY = lastY - th - 4;
      }
      tipNodes[x].setAttribute("transform","translate(" + (parseInt(this.evtX) + 30) + "," + lastY + ")");
      if ((parseInt(tipWidth) + parseInt(this.evtX)) > totalW) {
        tipNodes[x].setAttribute("transform","translate(" + strt2 + "," + lastY + ")");
      }
  }
  tipGroup.setAttribute("transform","translate(0,0)");
  tipGroup.setAttribute("style","display:block");
  tipGroup.setAttribute("x",this.evtX);
  tipGroup.setAttribute("y",this.evtY - 3);
   tipGroup.setAttribute("width",tipWidth + 20);
  tipGroup.setAttribute("height",(50 + (((numTips + addLines) - 1) * 15)));
  if ((parseInt(tipWidth) + parseInt(this.evtX)) > totalW) {
      tipGroup.setAttribute("x",strt);
      if ((parseInt(this.evtY) + parseInt(th)) > parseInt(maxY)) {
        flipY = (parseInt(this.evtY) + parseInt(this.evtY)) - 6;
        tipGroup.setAttribute("transform","matrix(-1 0 0 -1 " + (parseInt(tipWidth)+ 40) + " " + flipY + ")");
      }
      else {
        tipGroup.setAttribute("transform","matrix(-1 0 0 1 " + (parseInt(tipWidth) + 40) + " 0)");
      }
  }
  else {
      if ((parseInt(this.evtY) + parseInt(th)) > parseInt(maxY)) {
        flipY = parseInt(this.evtY) + parseInt(this.evtY);
        tipGroup.setAttribute("height",(50 + (((numTips + addLines)) * 10)));
        tipGroup.setAttribute("transform","matrix(1 0 0 -1 0 " + flipY + ")");
      }
  }
  timend = this.svgdoc.getElementById("tipTime");
  timend.setAttribute("x",(parseInt(this.evtX) + (parseInt(tipWidth) / 2)));
  if ((parseInt(tipWidth) + parseInt(this.evtX)) > totalW) {
      timend.setAttribute("x",strt3);
  }
  if ((parseInt(this.evtY) + parseInt(th)) > parseInt(maxY)) {
      lastY = lastY;
  }
  timend.setAttribute("y",parseInt(lastY + 18 + (addLines * 15)));
  timend.setAttribute("style","display:block");
  tm = this.ToolTipTime();
  timend.firstChild.nodeValue = tm;
  this.tipTimerOff = setTimeout("tooltipOff" + this.wpq + "()",2500);
  }
  catch (e) {}
}
SVGObject.prototype.ToolTipOnTOX = _toolTipOnTOX;

function _showTip(x,y,tm) {    
  var colMaxs = new Array();
  colMaxs[0] = 12;
  colMaxs[1] = 0;
  colMaxs[2] = 0;
  colMaxs[3] = 20;
  var newtip;
  
  // font-size is always fixed at 10
  fs = 10;
  var  nd = this.svgdoc.getElementById("tl");
  for (i=0; i < this.tags.length; i++) {
    nd.firstChild.nodeValue = this.tags[i];
    wdth = nd.getComputedTextLength();
    if (wdth > colMaxs[1]) {
      colMaxs[1] = parseInt(wdth);
    }
  }
  
  for (i=0; i < this.vals.length; i++) {
    nd.firstChild.nodeValue = this.vals[i];
    // 21049 : if value node does not exist set display width to 1
    try {
      wdth = nd.getComputedTextLength();
    }
    catch (e) {
      wdth = 1;
    }
    if (wdth > colMaxs[2]) {
      colMaxs[2] = parseInt(wdth);
    }
  }

  var w = 24;
  for (i=0; i< colMaxs.length; i++) {
    w += colMaxs[i];
  }          

  nd.firstChild.nodeValue = tm;
  wdth = nd.getComputedTextLength();
  if (wdth > w) {
    w = wdth;
  }

  
  var h,ybase,xbase,tmx,tmy;
  h = ((this.tags.length + 1) * fs) + 25;
  newtip = tip.replace(/wdth/g,w);
  newtip = newtip.replace(/hgt/g,h);
  newtip = newtip.replace("xfrmX",x);
  newtip = newtip.replace("xfrmY",y);
  
  //21049 - show the tooltip to the right
  //22305 - add - check on clientH 
  if (( ((x + w) <= this.containerW) || (x < (w/2))) && ((y + h) <= this.clientH)) {
      newtip = newtip.replace("flipX","1");
      newtip = newtip.replace("flipY","1");
      ybase = 28 + y;
      xbase = 30 + x;
      tmx = (xbase - 24) + (w / 2);
      tmy = (this.evtY + h) - 4;
  }
  //21049 - show the tooltip to the left
  //22305 - add - check on clientH 
  if (((x + w) > this.containerW) && (x >=( w/2)) && ((y + h) <= this.clientH)) {
      newtip = newtip.replace("flipX","-1");
      newtip = newtip.replace("flipY","1");
      ybase = y + 26;
      xbase = (x - w) + 10;
      tmx = (xbase - 24) + (w / 2);
      tmy = (this.evtY + h) - 4;
  }
  // 21049 : show the tooltip to the right
  if ((((x + w) <= this.containerW) || (x < (w/2))) && ((y + h) > this.clientH)) {
      newtip = newtip.replace("flipX","1");
      newtip = newtip.replace("flipY","-1");
      ybase = (y - h) + fs;
      xbase = x + 28;
      tmx = (xbase - 24) + (w / 2);
      tmy = (this.evtY - fs) - 7;
  }
  // 21049 : show the tooltip to the left
  if (((x + w)  > this.containerW) && (x >= (w/2)) && ((y + h) > this.clientH)) {
      newtip = newtip.replace("flipX","-1");
      newtip = newtip.replace("flipY","-1");
      ybase = (y - h) + fs;
      xbase = (x - w) + 10;
      tmx = (xbase - 24) + (w / 2);
      tmy = (this.evtY - fs) - 7;
  }
                  
  var newtiptxt = '<g id="txtGroup" stroke="none" font-size="' + fs + '">';  
  var clr;
  for (var i=0; i < this.tags.length; i++) {
    xval = 0;
    clr1 = this.svgdoc.getElementById(this.mrkrs[i].substr(1)).getAttribute("stroke");
    clr2 = this.svgdoc.getElementById(this.mrkrs[i].substr(1)).getAttribute("fill");
    if ((clr2 == null) || (clr2 == "") || (clr2 == "none")) {
      clr = clr1;
    }
    else {
      clr = clr2;
    }
    
    newtiptxt += '<g stroke="' + clr + '">';
    newtiptxt += '<g transform="translate(' + xbase + ' ' + ( (ybase + (i*fs)) - 6) + ')">';
    
    //mrkrnd = this.svgdoc.getElementById(this.mrkrs[i]);
    newtiptxt += '<use x="0" y="0" xlink:href="' + this.mrkrs[i] + '"/>'; 
    newtiptxt += '</g>';
    xval = colMaxs[0]
    newtiptxt += '<text fill="' + clr + '" stroke="none" x="' + (xbase + 2 + xval) + '" y="' + ((ybase + (i*fs))) + '" style="text-anchor:start">';
    t = this.tags[i].replace(/&/g,  '&amp;');
    t = t.replace(/>/g,"&gt;");
    t = t.replace(/</g,"&lt;");
    t = t.replace(/'/g, "&apos;");
    t = t.replace(/"/g, '&quot;');
    
    newtiptxt += t;
    newtiptxt += '</text>';
    xval += colMaxs[1];
    newtiptxt += '<text fill="' + clr + '" stroke="none" x="' + (xbase + 2 + xval) + '" y="' + ((ybase + (i*fs))) + '" style="text-anchor:start">';
    newtiptxt += this.vals[i];
    newtiptxt += '</text>';
    xval += colMaxs[2];

    switch (this.valattribs[i]){
        case "ANNOTATED":
          newtiptxt += '<use x="' + (xbase + 2 + xval) + '" y="' + (ybase + (i*fs) - fs) + '" xlink:href="#ann"/>';
          break;
        case "QUESTIONABLE":
          newtiptxt += '<use x="' + (xbase + 2 + xval) + '" y="' + (ybase + (i*fs) - fs) + '" xlink:href="#que"/>';
          break;
        case "SUBSTITUTED":
          newtiptxt += '<use x="' + (xbase + 2 + xval) + '" y="' + (ybase + (i*fs) - fs) + '" xlink:href="#sub"/>';
          break;
    }
    newtiptxt += '</g>';
  }
  newtiptxt += '<text fill="black" stroke="none" x="' + tmx + '" y="' + tmy + '" style="text-anchor:middle">';
  newtiptxt += tm;
  newtiptxt += '</text>';
  newtiptxt += '</g>';
    
  tnode = this.svgdoc.getElementById("tGroup");
  newnd = this.svgScript.parseXML(newtip,this.svgdoc);
  tnode.parentNode.replaceChild(newnd,tnode);
  
  newnd = this.svgScript.parseXML(newtiptxt,this.svgdoc);
  tnode = this.svgdoc.getElementById("txtGroup");
  tnode.parentNode.replaceChild(newnd,tnode);
}
SVGObject.prototype.ShowTip= _showTip;


function doUpdate(updXML) {
  this.svgObject.DoUpdate(updXML);
}
function IsNumeric(sText)
{
    var ValidChars = "0123456789.,";
    var IsNumber=true;
    var Char;


    for (i = 0; i < sText.length && IsNumber == true; i++) 
    { 
        Char = sText.charAt(i); 
        if (ValidChars.indexOf(Char) == -1) 
        {
            IsNumber = false;
        }
    }

    return IsNumber;
}
