// JavaScript Diagram Builder 1.1
// Copyright (c) 2001 Lutz Tautenhahn, all rights reserved.
//
// The Author grants you a non-exclusive, royalty free, license to use,
// modify and redistribute this software, provided that this copyright notice
// and license appear on all copies of the software.
// This software is provided "as is", without a warranty of any kind.

// Adapted by Dr R Knott: ron (AT) ronknott (DOT) com

var _N_Dia=0, _N_Bar=0, _N_Dot=0, _N_Pix=0, _zIndex=0;
var _dSize = (navigator.appName == "Netscape") ? -1 : 1;
 

function Diagram(theLeft, theTop, theRight, theBottom)
{ var xmin, xmax, ymin, ymax;
  var right, left, bottom, top;
  var xtext="", ytext="", title="";
  this.XScale=1;
  this.YScale=1;
  this.ID="_Dia"+_N_Dia; _N_Dia++; _zIndex++;
  this.left   = theLeft;
  this.right  = theRight;
  this.top    = theTop;
  this.bottom = theBottom;
  this.zIndex=_zIndex;
  this.SetScale=_SetScale;
  this.SetText=_SetText;
  this.ScreenX=_ScreenX;
  this.ScreenY=_ScreenY;
  this.RealX=_RealX;
  this.RealY=_RealY;
  this.Fns=new Array();
  this.newFn=_newFn;  
  this.replaceFn=_replaceFn;
  this.deleteFn=_deleteFn;
  this.Draw=_Draw;
  this.SetVisibility=_SetVisibility;
  this.SetTitle=_SetTitle;
  this.Delete=_Delete;
  document.writeln("<div id='"+this.ID+ "'" //+" style='height:",theBottom-theTop,"px;'"
    +"></div>"); 
  return(this);
}

function _SetScale(theLeftX, theRightX, theBottomY, theTopY)
{ this.xmin = theLeftX;
  this.xmax = theRightX;
  this.ymin = theBottomY;
  this.ymax = theTopY;
}
function _SetText(theScaleX, theScaleY, theTitle)
{ this.xtext=theScaleX;
  this.ytext=theScaleY;
  this.title=theTitle;
}
function _ScreenX(theRealX)
{ return(Math.round((theRealX-this.xmin)/(this.xmax-this.xmin)*(this.right-this.left)+this.left));
}
function _ScreenY(theRealY)
{ return(Math.round((this.ymax-theRealY)/(this.ymax-this.ymin)*(this.bottom-this.top)+this.top));
}
function _RealX(theScreenX)
{ return(this.xmin+(this.xmax-this.xmin)*(theScreenX-this.left)/(this.right-this.left));
}
function _RealY(theScreenY)
{ return(this.ymax-(this.ymax-this.ymin)*(theScreenY-this.top)/(this.bottom-this.top));
}
function _sign(rr)
{ if (rr<0) return(-1); else return(1);
}

function _FN(FnTXT,Fncol)
{this.FnTxt=FnTXT;this.color=Fncol;
 this.P=new Array();
};
_FN.prototype.plot=plotPixels;
function plotPixels(D)
{var i,j,x; //alert("Plot "+D.left+":"+D.right+">"+this.FnTxt);
  for (i=D.left; i<=D.right; i++)
  {x = D.RealX(i);
    try
    { with (Math) j=eval(this.FnTxt);
    }
    catch(error)
    { alert(this.FnTxt+" can not be evaluated for x="+x);
      return;
    }
    if ((D.ymin<=j)&&(j<=D.ymax)) 
        {if(!this.P[i])this.P[i]=new Pixel(i,D.ScreenY(j),this.color)
         else {this.P[i].Color=this.color;
               this.P[i].MoveTo(i, D.ScreenY(j))}
        }
    else if(this.P[i])this.P[i].SetVisibility(false);
  }
};
function _newFn(fnTXT,col){
   this.Fns[this.Fns.length]=new _FN(fnTXT,col);
   //document.writeln(fnTXT, ' is funciton ',this.Fns.length,'<br>');
   this.Fns[this.Fns.length-1].plot(this)
  };
function _replaceFn(FnNb,fnTXT,colr){this.Fns[FnNb].fnTxt=fnTXT;
  if(arguments.length>2)this.Fns[FnNb].color=colr;
  this.Fns[FnNb].plot(this)
};
function _deleteFn(FnNb){//FnNb is index in Fns array
   this.Fns[FnNb]=null };

function _Draw(theDrawColor, theTextColor, isScaleText, thePlotTitle, onClickPlotJS)
{ if(arguments.length<5)onClickPlotJS="";
  if(arguments.length<4)thePlotTitle="";
  if(arguments.length<3)isScaleText=false;
  if(arguments.length<2)theTextColor="#000";
  if(arguments.length<1)theDrawColor="#00F";
  var ytick="&nbsp;",xtick="&nbsp;";  //ytick=" |",xtick=" &#151;";
  var x0,y0,i,j,itext,x,y,r,dx,dy,xr,yr,invdifx,invdify,deltax,deltay,ll,id=this.ID;
  //document.getElementById(id).title=_nvl(thePlotTitle,"");
  document.writeln(
    "<div onClick='"+_nvl(onClickPlotJS,"")+"' style='position:absolute; left:"+eval(this.left)+"; width:"
    +eval(this.right-this.left+_dSize)+"; top:"+eval(this.top)+"; height:"+eval(this.bottom-this.top+_dSize)
    +"; background-color:"+theDrawColor+"; color:"+theTextColor+";  z-index:"
    +this.zIndex+"'></div>");
  if (this.XScale==1)// Bottom edge ticks
  { dx=(this.xmax-this.xmin);
    if (Math.abs(dx)>0)
    { invdifx=(this.right-this.left)/(this.xmax-this.xmin);
      r=1;
      while (Math.abs(dx)>=100) { dx/=10; r*=10; }
      while (Math.abs(dx)<10) { dx*=10; r/=10; }
      if (Math.abs(dx)>=50) deltax=10*r*_sign(dx)
      else
      { if (Math.abs(dx)>=20) deltax=5*r*_sign(dx);
        else deltax=2*r*_sign(dx);
      }
      x=Math.floor(this.xmin/deltax)*deltax;
      itext=0;
      for (j=12; j>=-1; j--)
      { xr=x+j*deltax;
        x0=Math.round(this.left+(-this.xmin+x+j*deltax)*invdifx);
        if ((x0>=this.left)&&(x0<=this.right))
        { itext++;
          if ((itext!=2)||(!isScaleText)||this.xtext=="")
            document.writeln(
              "<div align=center style='position:absolute; left:"+eval(x0-50)+"; width:102; top:"
              +eval(this.bottom-9)+"; color:"+theTextColor
              +";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"
              +this.zIndex+"'> "+ytick+"<BR>"+eval(10*Math.round(xr/r)*r/10)+"</div>")
          else if(this.xtext!="")
            document.writeln(
              "<div align=center style='position:absolute; left:"+eval(x0-50)+"; width:102; top:"
              +eval(this.bottom-9)+"; color:"+theTextColor
              +";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"
              +this.zIndex+"'> "+ytick+"<BR>"+this.xtext+"</div>")
        }
      }
    }
  }
  else if (this.XScale>1)
  { dx=(this.xmax-this.xmin);
    if (Math.abs(dx)>0)
    { invdifx=(this.right-this.left)/(this.xmax-this.xmin);
      deltax=_DateInterval(Math.abs(dx))*_sign(dx);
      x=Math.floor(this.xmin/deltax)*deltax;
      itext=0;
      for (j=13; j>=-2; j--)
      { xr=x+j*deltax;
        x0=Math.round(this.left+(-this.xmin+x+j*deltax)*invdifx);
        if ((x0>=this.left)&&(x0<=this.right))
        { itext++;
          ll=_DateFormat(xr, Math.abs(deltax), this.XScale);
          if ((itext!=2)||(!isScaleText)||this.xtext=="") 
            document.writeln(
              "<div align=center style='position:absolute; left:"+eval(x0-50)+"; width:102; top:"
                     +eval(this.bottom-9)+"; color:"
                     +theTextColor+";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"
                     +this.zIndex+"'> "+ytick+"<BR>"+ll+"</div>")
          else if (this.xtext!="")
            document.writeln(
              "<div align=center style='position:absolute; left:"+eval(x0-50)+"; width:102; top:"
              +eval(this.bottom-9)+"; color:"
              +theTextColor+";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"
              +this.zIndex+"'> "+ytick+"<BR>"+this.xtext+"</div>")
        }
      }
    }
  };
  if (this.YScale==1)// LHS ticks
  { dy=this.ymax-this.ymin;
    if (Math.abs(dy)>0)
    { invdify=(this.bottom-this.top)/(this.ymax-this.ymin);
      r=1;
      while (Math.abs(dy)>=100) { dy/=10; r*=10; }
      while (Math.abs(dy)<10) { dy*=10; r/=10; }
      if (Math.abs(dy)>=50) deltay=10*r*_sign(dy)
      else
      { if (Math.abs(dy)>=20) deltay=5*r*_sign(dy)
        else deltay=2*r*_sign(dy);
      }
      y=Math.floor(this.ymax/deltay)*deltay;
      itext=0;
      for (j=-1; j<=12; j++)
      { yr=y-j*deltay;
        y0=Math.round(this.top+(this.ymax-y+j*deltay)*invdify);
        if ((y0>=this.top)&&(y0<=this.bottom))
        { itext++;
           var str="";
          if((itext!=2)||(!isScaleText)||this.ytext=="")
           document.writeln("<div align=right style='position:absolute; left:"+eval(this.left-100)+"; width:107; top:"+eval(y0-8)
              +"; color:"+theTextColor+";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"
              +this.zIndex+"'>"+eval(Math.round(10*yr/r)*r/10)+" "+xtick+"</div>") 
          else if(this.ytext!="")
            document.writeln("<div align=right style='position:absolute; left:"+eval(this.left-100)+"; width:107; top:"+eval(y0-8)
              +"; color:"+theTextColor+";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"
              +this.zIndex+"'>"+this.ytext+" "+xtick+"</div>")
        }
      };
    }
  }
  else if (this.YScale>1)
  { dy=this.ymax-this.ymin;
    if (Math.abs(dy)>0)
    { invdify=(this.bottom-this.top)/(this.ymax-this.ymin);
      deltay=_DateInterval(Math.abs(dy))*_sign(dy);;
      y=Math.floor(this.ymax/deltay)*deltay;
      itext=0;
      for (j=-2; j<=13; j++)
      { yr=y-j*deltay;
        y0=Math.round(this.top+(this.ymax-y+j*deltay)*invdify);
        if ((y0>=this.top)&&(y0<=this.bottom))
        { itext++;
          ll=_DateFormat(yr, Math.abs(deltay), this.YScale);
          if ((itext!=2)||(!isScaleText)||this.ytext=="")
            document.writeln(
              "<div align=right style='position:absolute; left:"+eval(this.left-100)+"; width:107; top:"
              +eval(y0-8)+"; color:"+theTextColor
              +";font-size:10pt;line-height:12pt;font-weight:normal; z-index:"
              +this.zIndex+"'>"+ll+" "+xtick+"</div>")
          else if(this.ytext!="")
            document.writeln(
              "<div align=right style='position:absolute; left:"+eval(this.left-100)+"; width:107; top:"
              +eval(y0-8)+"; color:"+theTextColor+
              ";font-size:10pt;line-height:12pt;font-weight:normal; z-index:"+this.zIndex+"'>"
              +this.ytext+" "+xtick+"</div>")
        }
      }
    }
  }
  if(this.title!="")
     document.writeln(
    "<div align=center style='position:absolute; left:"+this.left+"; width:"+eval(this.right-this.left)+"; top:"
        +eval(this.top-20)+"; color:"+theTextColor+
       ";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:normal; z-index:"+this.zIndex+"'>"+this.title+"</div>")
};

function Bar(theLeft, theTop, theRight, theBottom, theDrawColor, theText, theTextColor, thePlotTitle, onClickPlotJS)
{ this.ID="_Bar"+_N_Bar; _N_Bar++; _zIndex++;
  this.left=theLeft;
  this.top=theTop;
  this.right=theRight;
  this.bottom=theBottom;
  this.DrawColor=theDrawColor;
  this.Text=theText;
  this.TextColor=theTextColor;
  this.SetVisibility=_SetVisibility;
  this.SetText=_SetBarText;
  this.SetTitle=_SetTitle;
  this.MoveTo=_MoveTo;
  this.ResizeTo=_ResizeTo;
  this.Delete=_Delete;
  if (_nvl(theText,"")!="") document.writeln("<div id='"+this.ID+"' onClick='"+_nvl(onClickPlotJS,"")
  +"' style='position:absolute;left:"+theLeft+";top:"+theTop+";width:"+eval(theRight-theLeft)+";height:"
  +eval(theBottom-theTop)+";background-color:"+theDrawColor+";color:"+theTextColor
  +";font-size:10pt;line-height:12pt;font-family:Verdana;font-weight:bold;z-index:"
  +_zIndex+"' title='"+_nvl(thePlotTitle,"")+"' align=center>"+theText+"</div>");
  else document.writeln("<div id='"+this.ID+"' onClick='"+_nvl(onClickPlotJS,"")
  +"' style='position:absolute;left:"+theLeft+";top:"+theTop+";width:"+eval(theRight-theLeft)
  +";height:"+eval(theBottom-theTop)+";background-color:"+theDrawColor
  +";font-size:1pt;line-height:1pt;font-family:Verdana;font-weight:bold;z-index:"+_zIndex
  +"' title='"+_nvl(thePlotTitle,"")+"'>&nbsp;</div>");
  return(this);
}
function _SetBarText(theText)
{ var id=this.ID;
  document.getElementById(id).innerHTML=theText;
}
function Dot(theX, theY, theSize, theType, theColor, thePlotTitle, onClickPlotJS)
{ //Symbol=new Array("9632", "9633", "9679", "9675", "120", "9674", "9660", "9650");
  Symbol=new Array("149", "176", "42", "164", "215", "43");
  //   &bull;  &deg; ? x&o, &times; &loz; 
  this.dX=1+theSize;
  if ((theType)<3) this.dX-=Math.floor(theSize/4)+2;
  if ((theType)==3) this.dX-=Math.floor(theSize/4)+1;
  this.dY=theSize-1;
  if (((theType)!=1)&&((theType)!=2)) this.dY+=Math.floor(theSize/2)+1;
  this.ID="_Dot"+_N_Dot; _N_Dot++; _zIndex++;
  this.X=theX;
  this.Y=theY;
  this.Size=theSize;
  this.Type=theType;
  this.Color=theColor;
  this.SetVisibility=_SetVisibility;
  this.SetTitle=_SetTitle;
  this.MoveTo=_DotMoveTo;
  this.Delete=_Delete;
  document.writeln("<div id='"+this.ID+"' onClick='"+_nvl(onClickPlotJS,"")
  +"' style='position:absolute;left:"+eval(theX-this.dX)+";top:"+eval(theY-this.dY)
  +";width:"+eval(2*theSize)+";height:"+eval(2*theSize)+";color:"+theColor
  +";font-size:"+(2*theSize)+"pt;line-height:"+(2*theSize)
  +"pt;font-family:Verdana;font-weight:normal;z-index:"
  +_zIndex+"' title='"+_nvl(thePlotTitle,"")+"'>&#"+Symbol[theType]+";</div>");
  return(this);
};

function _DotMoveTo(theX, theY)
{ var id=this.ID;
  with (document.getElementById(id).style)
  { if (theX!="") left=eval(theX-this.dX);
    if (theY!="") top=eval(theY-this.dY);
    visibility="visible";
  }
}
function Pixel(theX, theY, theColor)
{ this.ID="_Pix"+_N_Pix; _N_Pix++; _zIndex++;
  this.X=theX;
  this.Y=theY;
  this.Color=theColor;
  this.SetVisibility=_SetVisibility;
  this.MoveTo=_MoveTo;
  this.Delete=_Delete;
  document.writeln("<div id='"+this.ID+"' style='position:absolute;left:"
  +theX+";top:"+theY+  ";background-color:"+theColor+
  ";color:"+theColor
  +";z-index:"
  +_zIndex+"'><img src='empty.gif'></div>");
  return(this);
}
function _SetVisibility(isVisible)
{ var id=this.ID;
  if (isVisible) document.getElementById(id).style.visibility="visible";
  else document.getElementById(id).style.visibility="hidden";
}
function _SetTitle(theTitle)
{ var id=this.ID;
  document.getElementById(id).title=theTitle;
}
function _MoveTo(theLeft, theTop)
{ var id=this.ID;
  with (document.getElementById(id).style)
  { if (theLeft!="") left=theLeft;
    if (theTop!="") top=theTop;
    visibility="visible";
  }
}
function _ResizeTo(theLeft, theTop, theWidth, theHeight)
{ var id=this.ID;
  with (document.getElementById(id).style)
  { if (theLeft!="") left=theLeft;
    if (theTop!="") top=theTop;
    if (theWidth!="") width=theWidth;
    if (theHeight!="") height=theHeight;
    visibility="visible";
  }
}
function _Delete()
{ var id=this.ID;
  document.getElementById(id).outerHTML="";
}
function _nvl(vv, rr)
{ if (vv==null) return(rr);
  return(vv);
}
