
//File Last Updated Feb 14, 2010

 window.onload=StartUp;

   //constants
   var MULTIVIEWCLIENTVERSION="4.51";
   var REQUESTDATAINTERVAL=2;    //"rest" time between loading cycles-- in TimerInterval counts.
   var TIMERINTERVAL=1000;        //how often timer event fires in ms
   var UNITIDLENGTH=4;
   var ELEVATEDGASTHRESHOLD=1000;    //Show yellow font if GasUnits above this-- Green if at or below.
   var ALERTGASTHRESHOLD=1500;       //Show Red if GasUnits above this.
   var MINIBALLPACKETLENGTH=50;
   var IBALLFIELDCOUNT=33;
   var MINWITSPACKETLENGTH=50;
   var MINWITSVALUELENGH=5;
   var MAXWAITFORDATA= 60;          //Max wait for complete response from server before aborting request.
   
   var MAXLEASENAMELENGTH=35;
   var BUMPDOWN=10;                 //pixels to move pop up window down
   var BUMPRIGHT=15;                //pixels to move pop up window right.
   var BITDEPTHMINDELTA=2;          //minimum distance in feet bit needs to be off bottom before registering as such
 

   //checkboxes
  var HideOffline=false;
  var ShowLastUpdateColumn=false;
  var ShowUptimeColumn=true;
  var ShowExAmpColumn=false;


  var XMLDataReady=false;
  var IsCustomSession=false;
  var ToolTip1=null;
  var ToolTip2=null;
  var FixedMessage=[];
  var AllData=[];
  var AllWITS=[];
  var DetailViewShowing=false;
  var RequestPending=false;
  var FirstPass=true;


   var strTableFontSize="<font size= \"3\">";
   var CustomSessionID="";
   var CookieIn="";
   var ServerReturnCode="200";
   var errmsg="";
   var XMLFileCreated=" ";
   var StatusCellClass="";
   var RequestID="";
   var RequestString="";

  
   var XMLDocIn;
   var IsDebugMode=false;
   var NewDataIn=false;
   var TableFontSizeNum=3;


   var LastAttemptIntervalID;
   var LastAttemptInterval=0;
   var DataAge=0;
   var TimerEventFlag=false;
   var GettingData=false;      //true when doing a transaction with web server.

   var xhr=false;
   var SessionID="";

   
   //only one of these per xml response file.
   var UnitCount=0;
   var SessionIDReturned="";
    //SessionRefresh is the time the session was started or
   //last refreshed (in milliseconds since epoch)
   var SessionRefresh=" ";
   var SessionTitle="";
   var NewXMLFileCreated="";


     //unit data
   var WorkingUnitIndex;

   var UnitID=[];
   var LeaseName=[];
  

   var LastUpdate=[];
   var WebPageAddr=[];
   var iBallRawPacket=[];
   var WITSRawPacket=[];
   var UnitUptime=[];
   var UpdateInterval=[];
   var IsKnownUnit=[];

     //Data from Bloodhound packet
     
     var JobNumber=[];
     var iBallPacketNumber=[];
     var HoleDepth=[];
     var GasUnits=[];
     var ROP=[];
     var ROPFtHr=[];
     var iBallTime=[];
     var iBallDate=[];
     var iBallErrorNumber=[];
     var RigVoltage=[];
     var RigFrequency=[];
     var InternalVolts=[];
     var ExtractorAmps=[];
     var O2=[];
     var CO2=[];
     var H2S=[];
     var InternalTemp=[];
     var SampleVac=[];
     var SampleVol=[];  //LPH
     var PriVoltage=[];
     var SecVoltage=[];
     var H2SVoltage=[];
     var CGVoltage=[];
     var CGTestID=[];
     var SampleMotor=[];  //motor %
     var HRMTemp=[];
     var ChromVac=[];
     var Attenuation=[];
     var RSSI=[];
     var C1Gas=[];
     var C2Gas=[];
     var C3Gas=[];
     var IC4Gas=[];
     var NC4Gas=[];
     var ExhaustPressure=[];
     var ColumnTemp=[];
     var iBallLagDepth=[];
     var iBallPacketChecksum=[];
     var IsChecksumMissing=[];
     var IsBadChecksum=[];
     var BadChecksumCounter=[];

     //Data from WITS packet         //WITS Codes
     var BitDepth=[];                //0108,0408
     var WOB=[];                     //0116,0117
     var RPM=[];                     //0120



//////////////////////////////////////////////////////////////////////////
function IncreaseTableFontSize(){
    TableFontSizeNum++;
    if (TableFontSizeNum>6) TableFontSizeNum=6;
    strTableFontSize="<font size= \""+ TableFontSizeNum + "\">";
    if (IsDebugMode) {
      var  strDisplay="<font color=\"RED\">Table Font Size:</font> " + TableFontSizeNum + "<br>";
      document.getElementById("FontSizeSetting").innerHTML= strDisplay;
    }
    RefreshDisplay();
}



/////////////////////////////////////////////////////////////////////////////
function DecreaseTableFontSize(){
    TableFontSizeNum--;
    if (TableFontSizeNum<1) TableFontSizeNum=1;
    strTableFontSize="<font size= \""+ TableFontSizeNum + "\">";
    if (IsDebugMode) {
      var  strDisplay="<font color=\"RED\">Table Font Size:</font> " + TableFontSizeNum + "<br>"; 
      document.getElementById("FontSizeSetting").innerHTML= strDisplay;
    }
    RefreshDisplay();
}


  //////////////////////////////////////////////////////////////////////////
 function ToggleHideOffline() {
      if (document.rf.HideOffline.checked) {
      HideOffline = true;
    } else {
      HideOffline = false;
    }

    WriteSettingsCookie();
    RefreshDisplay();

 }


 
////////////////////////////////////////////////////////////////////////////////
function ToggleLastUpdatedShow() {
    
    if (document.rf.ShowLastUpdateColumn.checked) {
      ShowLastUpdateColumn = true;
    } else {
      ShowLastUpdateColumn = false;
    }  

    WriteSettingsCookie();
    RefreshDisplay();
}


////////////////////////////////////////////////////////////////////////////////
function ToggleUptimeShow() {
    
    if (document.rf.ShowUptimeColumn.checked) {
        ShowUptimeColumn=true;
    } else {
        ShowUptimeColumn=false;
     }

    WriteSettingsCookie();
    RefreshDisplay();
}




////////////////////////////////////////////////////////////////////////////////
function ToggleExAmpsShow() {
    
    if (document.rf.ShowExAmpColumn.checked) {
       ShowExAmpColumn=true;
    }  else {
       ShowExAmpColumn=false;
    }

    WriteSettingsCookie();
    RefreshDisplay();
    
}


 /////////////////////////////////////////////////////////////////////////////
     
     function CreateGUID()
     {
        var guid, i, j;
        guid = '';
        for(j=0; j<32; j++){
           if( j == 8 || j == 12|| j == 16|| j == 20) guid = guid + '-';
           i = Math.floor(Math.random()*16).toString(16).toUpperCase();
           guid = guid + i;
        }
        
       return guid;
         
} 


 ////////////////////////////////////////////////////////////////////////////

    function GetCurrentTimeAsString () {
	    var now = new Date();
	    var hours = now.getHours();
	    var minutes = now.getMinutes();
	    var seconds = now.getSeconds();
	    var timeValue = "" + hours;
	    timeValue += ((minutes < 10) ? ":0" : ":") + minutes;
	    timeValue += ((seconds < 10) ? ":0" : ":") + seconds;
       return(timeValue);

    }


 /////////////////////////////////////////////////////////////////////////
 function IsDefined (VarIn)   {

     try {
       if (typeof(VarIn)=='undefined') {
             return false;
       } else {
           return true;
       }
     }catch(e) {
         return false;
     }
         
 }


        
 ////////////////////////////////////////////////////////////////////////////
 
 function Trim(strIn) {

     if (strIn==undefined) return "";
     
     var strOut=strIn + "  ";

    try {
       return strOut.replace(/^\s+|\s+$/g,"");
    } catch (e) {
        return (strIn+"");
     }
    return "";
}


/////////////////////////////////////////////////////////////////////////////

function ZeroPad(NumberIn,TotalSize){

 var numZeropad = NumberIn + '';

    
    while(numZeropad.length < TotalSize) {
       numZeropad = "0" + numZeropad;
    }
    return numZeropad;
}


/////////////////////////////////////////////////////////////////////////////

function XMLToHTML(XMLObjIn) {

    var HTMLOut;

    try {


    HTMLOut = (new XMLSerializer()).serializeToString(XMLObjIn);

    } catch (e) {
        try {
         // Internet Explorer.
         HTMLOut = XMLObjIn.xml;
       }
       catch (e2) {

       return "Error Converting XML File to string."
       }

    }


   //add in HTML line breaks and colorize the tags.
   //Indenting would be nice, but how?
    HTMLOut=HTMLOut.replace(/>\s+</g,">___XXX___<");
    HTMLOut=HTMLOut.replace(/></g,">___XXX___<");
    HTMLOut=HTMLOut.replace(/</g,"&lt;");
    HTMLOut=HTMLOut.replace(/>/g,"&gt;");
    HTMLOut=HTMLOut.replace(/\&lt\;/g,"<font color=\"BLUE\">&lt;");
    HTMLOut=HTMLOut.replace(/\&gt\;/g,"&gt;</font>");
    HTMLOut=HTMLOut.replace(/___XXX___/g,"<BR>");

  return HTMLOut;
}


/////////////////////////////////////////////////////////////////////////
function WriteSettingsCookie() {
    var CookieOut="";
    var ExpireDate;

    if (HideOffline) {
        CookieOut +="T";
    } else {
        CookieOut +="F";
    }
    CookieOut +="_";


    if (ShowLastUpdateColumn) {
        CookieOut +="T";
    } else {
        CookieOut +="F";
    }
    CookieOut +="_";

    if (ShowUptimeColumn) {
        CookieOut +="T";
    } else {
        CookieOut +="F";
    }
    CookieOut +="_";

    if (ShowExAmpColumn) {
       CookieOut +="T";
    } else {
       CookieOut +="F";
    }



    //set new cookie to expire 6 months from now.
    ExpireDate=new Date();
    ExpireDate.setMonth(ExpireDate.getMonth() + 6);


    CookieOut = "Settings=" + escape(CookieOut);
    CookieOut += ";expires=" + ExpireDate.toGMTString();
    document.cookie=CookieOut;

    if (IsDebugMode)  document.getElementById("CookieIn").innerHTML="<font color=\"RED\">Cookie:</font> " + unescape(document.cookie) + "<br>";
    

}

//////////////////////////////////////////////////////////////////////////////
function ParseCookies() {
   var strTemp;
   var Split0=[]; 
   var Split1=[];
   var SplitList=[];
   var idxUnit=-1;
   var UnitsFound=false;
   var idxCookie;
   var CookiePart;
   var CookieNameIn;
   var CookieDataIn;


//different cookies seperated by "; "
//cookie name and cookie value seperated by =
//in settings, values seperated by _
//in session info, unitid and leasename seperated  by = with
//each pair seperated by a ;

 
   Split0=CookieIn.split("; ");

   if (Split0.length<1) {
       return false;
   }

  
   for (idxCookie=0;idxCookie<Split0.length;idxCookie++) {
       
        CookiePart=Split0[idxCookie].split("=");
        CookieNameIn=CookiePart[0];
        CookieDataIn=CookiePart[1];


       if (CookieNameIn=="Settings"){
           strTemp=unescape(CookieDataIn);
           SplitList=strTemp.split("_");

           //HideOffline
           if (SplitList.length>0){
               strTemp=SplitList[0];
               if (strTemp=="T"){
                   document.rf.HideOffline.checked=true;
                   HideOffline=true
               } else{
                    document.rf.HideOffline.checked=false;
                   HideOffline=false;
               }
           }

          

           //ShowLastUpdateColumn
           if (SplitList.length>1){
               strTemp=SplitList[1];
               if (strTemp=="T"){
                   document.rf.ShowLastUpdateColumn.checked=true;
                   ShowLastUpdateColumn=true
               } else{
                    document.rf.ShowLastUpdateColumn.checked=false;
                   ShowLastUpdateColumn=false;
               }
           }

           //ShowUptimeColumn
           if (SplitList.length>2){
               strTemp=SplitList[2];
               if (strTemp=="T"){
                   document.rf.ShowUptimeColumn.checked=true;
                   ShowUptimeColumn=true
               } else{
                    document.rf.ShowUptimeColumn.checked=false;
                   ShowUptimeColumn=false;
               }
           }

           //ShowExAmpColumn
           if (SplitList.length>3){
               strTemp=SplitList[3];
               if (strTemp=="T"){
                   document.rf.ShowExAmpColumn.checked=true;
                   ShowExAmpColumn=true
               } else{
                    document.rf.ShowExAmpColumn.checked=false;
                   ShowExAmpColumn=false;
               }

           }
       }

       if (CookieNameIn=="UnitList"){
            strTemp=unescape(CookieDataIn);
           SplitList=strTemp.split(";");


           if (SplitList.length<1) {
              UnitsFound=false;
           } else {

               for (var i=0;i<SplitList.length;i++) {
                    Split1=SplitList[i].split("=");
                    if (Split1.length==2) {

                       // normal case: unitid=leasename
                       if (Split1[0].length==UNITIDLENGTH)  {
                          idxUnit++;
                          UnitID[idxUnit]=Split1[0];
                          LeaseName[idxUnit]=Split1[1];
                          if (LeaseName[idxUnit]==undefined) LeaseName[idxUnit]=" ";
                          IsKnownUnit[idxUnit]=true;
                          UnitsFound=true;
                       }

                       //special case: unitid1-unitid2=leasename
                       //indicates a range of units from unitid1 through unitid2
                       if (Split1[0].length==((2*UNITIDLENGTH)+1)){
                           var RangeIn=Split1[0];
                           var LeaseNameIn=Split1[1];
                           if (LeaseNameIn==undefined) LeaseNameIn=" ";

                           var Range1=RangeIn.substr(0,UNITIDLENGTH);
                           var Range2=RangeIn.substr(UNITIDLENGTH+2,UNITIDLENGTH);

                           if (isNaN(Range1) || isNaN(Range2) || Range1>=Range2) continue;

                           for (var i2=Range1;i2<=Range2;i2++){
                            idxUnit++;
                            UnitID[idxUnit]=ZeroPad(i2,UNITIDLENGTH)
                            LeaseName[idxUnit]=LeaseNameIn;
                            IsKnownUnit[idxUnit]=true;
                            UnitsFound=true;
                           }

                       }

                    }
               }
              
           }
         }


         
   }
  return UnitsFound;
   
} 
   
 ////////////////////////////////////////////////////////////////////////   
    
    function ConvertTimeToString (DateTimeInput) {
    
    	//convert YYYYMMDDHHmmss  to more readable format.
        //add in a  difference value showing number of days diff between
        //     web browswer's date and the incoming last update value.
    
    
        
        DateTimeInput=Trim(DateTimeInput);
        if (DateTimeInput.length!=14) return "&nbsp;";


        var YearIn;
        var MonthIn;
        var DayIn;
        var HourIn;
        var MinIn;
        var SecIn;
        var strNewTime;

       YearIn=DateTimeInput.substr(0,4);
       MonthIn=DateTimeInput.substr(4,2);
       DayIn=DateTimeInput.substr(6,2);
       HourIn=DateTimeInput.substr(8,2);
       MinIn=DateTimeInput.substr(10,2);
       SecIn=DateTimeInput.substr(12,2);

       strNewTime= MonthIn + "/" + DayIn + "/"+ YearIn + "  " + HourIn+":"+MinIn+":"+SecIn;


      //Show Date Diff

        //Set 1 day in milliseconds
          var one_day=1000*60*60*24;
          try {
               //MonthIn-1 because Javascript months are zero based for some crazy reason
               var TimeIn=new Date(YearIn,MonthIn-1,DayIn,HourIn,MinIn,SecIn);
               var TimeNow=new Date();
               var TimeDiffInMS=TimeNow-TimeIn;
               var TimeDiffInDays=TimeDiffInMS/one_day;

               TimeDiffInDays=Math.round(TimeDiffInDays);

               if (TimeDiffInDays>=0) {
                   strNewTime=strNewTime + " - <b>"+TimeDiffInDays+"</b>";
               } else{
                   strNewTime=strNewTime + " - <b>(0)</b>"
               }

          }catch (e) {}


       

       return strNewTime;
        
 }


//////////////////////////////////////////////////////////////////////////////

   function GetParamFromThisURL(ParameterIn)
      {
        var name;
        var ParameterOut;
        var ParamList;

        name=ParameterIn.toLowerCase();
        ParamList= window.location.href.toLowerCase();

        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( ParamList );
        if( results == null) {
          ParameterOut="";
        } else {
          name=results[1];
          ParameterOut=CleanUpParameterIn(name);
        }

        return ParameterOut;
    }


 ///////////////////////////////////////////////////////////////////////////

   function CleanUpParameterIn(ParamIn) {
       	if (ParamIn =="") {
       	  return("");
       	}
       	ParamIn=ParamIn.replace(/\%20/g," ");
       	ParamIn=ParamIn.replace(/\%22/g,"");
       	return (ParamIn);
   }


  //////////////////////////////////////////////////////////////////////////
  function UpdateTimeCounter() {


       //Watchdog-- see if really locked up or just not doing anything.
      var HeartBeat=CreateGUID();
      if (IsDebugMode) document.getElementById("Watchdog").innerHTML= "<font color=\"RED\">HeartBeat:</font> <b>" + HeartBeat +"</b><br>";
     
       if (TimerEventFlag) {
           LastAttemptIntervalID=setTimeout("UpdateTimeCounter()",TIMERINTERVAL);
           return;
       }
       TimerEventFlag= true;

       var DataAgeDisplay="&nbsp;<a style=\"font-size: small;\">"

       if ((LastAttemptInterval >= REQUESTDATAINTERVAL) && (!GettingData)) {
         LastAttemptInterval=0;
         InitDataRequest();
         TimerEventFlag=false;
         LastAttemptIntervalID=setTimeout("UpdateTimeCounter()",TIMERINTERVAL);
         return;
       }

       if (!GettingData) {
           DataAge++;
           LastAttemptInterval++;
           DataAgeDisplay +="Data Request Complete.";
       }


       if (GettingData && !RequestPending){
           var GoFlag=false;

           //Skip unlisted units.
           while (!GoFlag && WorkingUnitIndex<=UnitID.length-1){
               WorkingUnitIndex++;
               if (IsKnownUnit[WorkingUnitIndex]) GoFlag=true;
           }
           if (WorkingUnitIndex<=UnitID.length-1){
              RequestXMLFile();
           } else {
              FinishOutDataRequest();
              DataAgeDisplay +="Data Request Complete.";
           }
       }

       if (GettingData && (WorkingUnitIndex<UnitID.length-1)){
              DataAgeDisplay +="Requesting Unit " + UnitID[WorkingUnitIndex];
       }
 
       DataAgeDisplay +="</a>&nbsp;";


       document.getElementById("DataAge").innerHTML= DataAgeDisplay;

   
   if (IsDebugMode) {
       var strDisplay;
       strDisplay="<font color=\"RED\">Seconds since last attempt:</font> " + LastAttemptInterval + "<br>";
       document.getElementById("LastServerRequest").innerHTML= strDisplay;
       document.getElementById("DataAgeDisplayOut").innerHTML= "<font color=\"RED\">Data Age:</font> <b>" + DataAge +"</b><br>";
   }
   
   
   TimerEventFlag= false;
   LastAttemptIntervalID=setTimeout("UpdateTimeCounter()",TIMERINTERVAL);
   }
   
   
 



//////////////////////////////////////////////////////////////////////////////

function ParseBloodhoundData() {

       if (!IsDefined(UnitID[WorkingUnitIndex]))           UnitID[WorkingUnitIndex]=" ";
       if (!IsDefined(JobNumber[WorkingUnitIndex]))        JobNumber[WorkingUnitIndex]=" ";
       if (!IsDefined(iBallDate[WorkingUnitIndex]))        iBallDate[WorkingUnitIndex]=" ";
       if (!IsDefined(iBallTime[WorkingUnitIndex]))        iBallTime[WorkingUnitIndex]=" ";
       if (!IsDefined(HoleDepth[WorkingUnitIndex]))        HoleDepth[WorkingUnitIndex]=" ";
       if (!IsDefined(GasUnits[WorkingUnitIndex]))        GasUnits[WorkingUnitIndex]=" ";
       if (!IsDefined(O2[WorkingUnitIndex]))               O2[WorkingUnitIndex]=" ";
       if (!IsDefined(CO2[WorkingUnitIndex]))              CO2[WorkingUnitIndex]=" ";
       if (!IsDefined(Attenuation[WorkingUnitIndex]))      Attenuation[WorkingUnitIndex]=" ";
       if (!IsDefined(InternalTemp[WorkingUnitIndex]))     InternalTemp[WorkingUnitIndex]=" ";
       if (!IsDefined(ROP[WorkingUnitIndex]))              ROP[WorkingUnitIndex]=" ";
       if (!IsDefined(ROPFtHr[WorkingUnitIndex]))          ROPFtHr[WorkingUnitIndex]=" ";
       if (!IsDefined(SampleVol[WorkingUnitIndex]))        SampleVol[WorkingUnitIndex]=" ";
       if (!IsDefined(SampleVac[WorkingUnitIndex]))        SampleVac[WorkingUnitIndex]=" ";
       if (!IsDefined(InternalVolts[WorkingUnitIndex]))    InternalVolts[WorkingUnitIndex]=" ";
       if (!IsDefined(PriVoltage[WorkingUnitIndex]))       PriVoltage[WorkingUnitIndex]=" ";
       if (!IsDefined(SecVoltage[WorkingUnitIndex]))       SecVoltage[WorkingUnitIndex]=" ";
       if (!IsDefined(CGTestID[WorkingUnitIndex]))         CGTestID[WorkingUnitIndex]=" ";
       if (!IsDefined(CGVoltage[WorkingUnitIndex]))        CGVoltage[WorkingUnitIndex]=" ";
       if (!IsDefined(H2SVoltage[WorkingUnitIndex]))       H2SVoltage[WorkingUnitIndex]=" ";
       if (!IsDefined(H2S[WorkingUnitIndex]))              H2S[WorkingUnitIndex]=" ";
       if (!IsDefined(iBallErrorNumber[WorkingUnitIndex])) iBallErrorNumber[WorkingUnitIndex]="998";
       if (!IsDefined(SampleMotor[WorkingUnitIndex]))      SampleMotor[WorkingUnitIndex]=" ";
       if (!IsDefined(RSSI[WorkingUnitIndex]))             RSSI[WorkingUnitIndex]=" ";
       if (!IsDefined(RigVoltage[WorkingUnitIndex]))       RigVoltage[WorkingUnitIndex]=" ";
       if (!IsDefined(RigFrequency[WorkingUnitIndex]))     RigFrequency[WorkingUnitIndex]=" ";
       if (!IsDefined(ExtractorAmps[WorkingUnitIndex]))    ExtractorAmps[WorkingUnitIndex]=" ";
       if (!IsDefined(HRMTemp[WorkingUnitIndex]))          HRMTemp[WorkingUnitIndex]=" ";
       if (!IsDefined(ChromVac[WorkingUnitIndex]))         ChromVac[WorkingUnitIndex]=" ";
       if (!IsDefined(C1Gas[WorkingUnitIndex]))            C1Gas[WorkingUnitIndex]=" ";
       if (!IsDefined(C2Gas[WorkingUnitIndex]))            C2Gas[WorkingUnitIndex]=" ";
       if (!IsDefined(C3Gas[WorkingUnitIndex]))            C3Gas[WorkingUnitIndex]=" ";
       if (!IsDefined(IC4Gas[WorkingUnitIndex]))           IC4Gas[WorkingUnitIndex]=" ";
       if (!IsDefined( NC4Gas[WorkingUnitIndex]))          NC4Gas[WorkingUnitIndex]=" ";
       if (!IsDefined(ExhaustPressure[WorkingUnitIndex]))  ExhaustPressure[WorkingUnitIndex]="";
       if (!IsDefined(ColumnTemp[WorkingUnitIndex]))       ColumnTemp[WorkingUnitIndex]="";
       if (!IsDefined(iBallLagDepth[WorkingUnitIndex]))    iBallLagDepth[WorkingUnitIndex]="";


      iBallPacketNumber[WorkingUnitIndex]=" ";
      iBallPacketChecksum[WorkingUnitIndex]=" ";
      IsChecksumMissing[WorkingUnitIndex]=true;


     iBallRawPacket[WorkingUnitIndex]=Trim(iBallRawPacket[WorkingUnitIndex]);


     if (iBallRawPacket[WorkingUnitIndex].length < MINIBALLPACKETLENGTH) {
         iBallErrorNumber[WorkingUnitIndex]="998";
         return;
     }

         //fields are delimited by commas in iBall packet
         var iBallSplit=iBallRawPacket[WorkingUnitIndex].split(",");

         if (iBallSplit.length<IBALLFIELDCOUNT) return;

          //first field actually contains two values divided by an underscore:
          //Unit ID and Job Number.
         var strSplit=iBallSplit[0].split("_");

         JobNumber[WorkingUnitIndex]=strSplit[1];
         iBallDate[WorkingUnitIndex]=iBallSplit[1];
         iBallTime[WorkingUnitIndex]=iBallSplit[2];
         HoleDepth[WorkingUnitIndex]=iBallSplit[3];

         GasUnits[WorkingUnitIndex]=iBallSplit[4];

         O2[WorkingUnitIndex]=iBallSplit[5];
         CO2[WorkingUnitIndex]=iBallSplit[6];
         Attenuation[WorkingUnitIndex]=iBallSplit[7];
         InternalTemp[WorkingUnitIndex]=iBallSplit[8];

         ROP[WorkingUnitIndex]=iBallSplit[9];


         ROPFtHr[WorkingUnitIndex]=iBallSplit[10];
         SampleVol[WorkingUnitIndex]=iBallSplit[11];
         SampleVac[WorkingUnitIndex]=iBallSplit[12];
         InternalVolts[WorkingUnitIndex]=iBallSplit[13];
         PriVoltage[WorkingUnitIndex]=iBallSplit[14];
         SecVoltage[WorkingUnitIndex]=iBallSplit[15];
         CGTestID[WorkingUnitIndex]=iBallSplit[16];
         CGVoltage[WorkingUnitIndex]=iBallSplit[17];
         H2SVoltage[WorkingUnitIndex]=iBallSplit[18];
         H2S[WorkingUnitIndex]=iBallSplit[19];
         iBallErrorNumber[WorkingUnitIndex]=iBallSplit[20];
         SampleMotor[WorkingUnitIndex]=iBallSplit[21];
         RSSI[WorkingUnitIndex]=iBallSplit[22];
         RigVoltage[WorkingUnitIndex]=iBallSplit[23];
         RigFrequency[WorkingUnitIndex]=iBallSplit[24];
         ExtractorAmps[WorkingUnitIndex]=iBallSplit[25];
         HRMTemp[WorkingUnitIndex]=iBallSplit[26];
         ChromVac[WorkingUnitIndex]=iBallSplit[27];
         iBallPacketNumber[WorkingUnitIndex]=iBallSplit[28];
         C1Gas[WorkingUnitIndex]=iBallSplit[29];
         C2Gas[WorkingUnitIndex]=iBallSplit[30];
         C3Gas[WorkingUnitIndex]=iBallSplit[31];
         IC4Gas[WorkingUnitIndex]=iBallSplit[32];
         NC4Gas[WorkingUnitIndex]=iBallSplit[33];
         ExhaustPressure[WorkingUnitIndex]=iBallSplit[34];
         ColumnTemp[WorkingUnitIndex]=iBallSplit[35];
         iBallLagDepth[WorkingUnitIndex]=iBallSplit[36];


      //Bloodhounds with older firmware may be missing fields between NC4Gas and the checksum.
      //You can tell a value is actually the checksum because it starts with a C
      //Make sure we're not mistaking a checksum value for ExhaustPressure, ColumnTemp, or iBallLagDepth

      //There also may be NO checksum value on older still Bloodhound versions.

      try {

          if (ExhaustPressure[WorkingUnitIndex].indexOf("C")==0) {
              ExhaustPressure[WorkingUnitIndex]="";
              ColumnTemp[WorkingUnitIndex]="";
              iBallLagDepth[WorkingUnitIndex]="";
          }

          if (ColumnTemp[WorkingUnitIndex].indexOf("C")==0) {
              ExhaustPressure[WorkingUnitIndex]="";
              ColumnTemp[WorkingUnitIndex]="";
              iBallLagDepth[WorkingUnitIndex]="";
          }

          if (iBallLagDepth[WorkingUnitIndex].indexOf("C")==0) {
              ExhaustPressure[WorkingUnitIndex]="";
              ColumnTemp[WorkingUnitIndex]="";
              iBallLagDepth[WorkingUnitIndex]="";
          }


      } catch (e) {
           ExhaustPressure[WorkingUnitIndex]="";
           ColumnTemp[WorkingUnitIndex]="";
           iBallLagDepth[WorkingUnitIndex]="";

      }



      IsChecksumMissing[WorkingUnitIndex]=false;


     //look for the C that indicates the checksum value
     if (iBallRawPacket[WorkingUnitIndex].indexOf("C")==-1) {
          IsChecksumMissing[WorkingUnitIndex]=true;
      } else {
          IsChecksumMissing[WorkingUnitIndex]=true;
       }


      if (!IsChecksumMissing) {

         //the checksum is the numeric value after the C and before the final comma
         iBallPacketChecksum[WorkingUnitIndex]=iBallRawPacket[WorkingUnitIndex].substr(iBallRawPacket[WorkingUnitIndex].indexOf("C")+1);
         iBallPacketChecksum[WorkingUnitIndex]=iBallPacketChecksum[WorkingUnitIndex].substr(0,iBallPacketChecksum[WorkingUnitIndex].indexOf(","));

         //Force JavaScript to treat iBallPacketChecksum like a number instead of a string
         iBallPacketChecksum[WorkingUnitIndex] =iBallPacketChecksum[WorkingUnitIndex]*1;

         //now, in order to calculate the checksum, remove the C and everything after
         //from the packet and return the * char at the front.
        iBallRawPacket[WorkingUnitIndex]=iBallRawPacket[WorkingUnitIndex].substr(0,iBallRawPacket[WorkingUnitIndex].indexOf("C"));
        iBallRawPacket[WorkingUnitIndex]="*"+iBallRawPacket[WorkingUnitIndex];

         //Calculate the checksum and see if it matches what was given.

         var CalcChecksum=0;

         for (i=0;i<iBallRawPacket[WorkingUnitIndex].length;i++) {

             var v2=iBallRawPacket[WorkingUnitIndex].substr(i,1);
             var v=v2.charCodeAt(0);
             CalcChecksum+=v;
             if (CalcChecksum>255) CalcChecksum-=256;
         }


          if (CalcChecksum==iBallPacketChecksum[WorkingUnitIndex]) {
              IsBadChecksum[WorkingUnitIndex]=false;
              BadChecksumCounter[WorkingUnitIndex]=0;
          } else {
              IsBadChecksum[WorkingUnitIndex]=true;
              BadChecksumCounter[WorkingUnitIndex]++;
          }

      } else {
          BadChecksumCounter[WorkingUnitIndex]=0;
          IsBadChecksum[WorkingUnitIndex]=false;

      }

      iBallLagDepth[WorkingUnitIndex]=Trim(iBallLagDepth[WorkingUnitIndex]);
      if (iBallLagDepth[WorkingUnitIndex]=="0.0" || iBallLagDepth[WorkingUnitIndex]=="0") iBallLagDepth[WorkingUnitIndex]=" ";
     

}



//////////////////////////////////////////////////////////////////////////////

function ParseWITSData() {
    
    var WITSCode;
   	var WITSVal;
   	var WITSLine;
    var WITSTitle; 
    var strTemp; 
    
   


	  if (!IsDefined(BitDepth[WorkingUnitIndex])) BitDepth[WorkingUnitIndex]=" ";
	  if (!IsDefined(AllWITS[WorkingUnitIndex])) AllWITS[WorkingUnitIndex]=" ";
	  if (!IsDefined(WOB[WorkingUnitIndex])) WOB[WorkingUnitIndex]=" ";
	  if (!IsDefined(RPM[WorkingUnitIndex])) RPM[WorkingUnitIndex]=" ";
  
  


       WITSRawPacket[WorkingUnitIndex]=Trim(WITSRawPacket[WorkingUnitIndex]);


       //clear out old wits data if no new wits data in downloaded XML file.
       if (WITSRawPacket[WorkingUnitIndex].length < MINWITSPACKETLENGTH) {
	   
		BitDepth[WorkingUnitIndex]=" ";
		AllWITS[WorkingUnitIndex]=" ";
		WOB[WorkingUnitIndex]=" ";
		RPM[WorkingUnitIndex]=" ";
		
	    return;
	   }
	   
	   
	   

      //WITS Packet is divided by commas
       var WitsSplit=WITSRawPacket[WorkingUnitIndex].split(",");
       var WSMax=WitsSplit.length - 1;

     //Stuff we already have or don't need:
     //WitsSplit[0] should have nothing
     //WitsSplit[1] should have unitID and job #
     //WitsSplit[2] should have year/month/date
     //WitsSplit[3] should have time
     //WitsSplit[4] should have packet number



     AllWITS[WorkingUnitIndex]="<select STYLE=\"Width:100%;font-size:0.74em;\" size=\"30\">";
     for (var i2=4; i2<= WSMax; i2++) {
     	strTemp=WitsSplit[i2];
     	if (strTemp.length<MINWITSVALUELENGH) continue;
        //seperate the data type code (first 4 digits)
        //from the data (the rest of the substring)
     	WITSCode=strTemp.substr(0,4);
     	WITSVal = strTemp.substr(4,strTemp.length-1);
        //values we may want to show in the main display.  Throw everything
        //else into one long string.
        switch(WITSCode) {
            case "0108" : BitDepth[WorkingUnitIndex]=WITSVal; break;
            case "0408" : BitDepth[WorkingUnitIndex]=WITSVal; break;
            case "0116" : WOB[WorkingUnitIndex]=WITSVal; break;
            case "0117" : WOB[WorkingUnitIndex]=WITSVal; break;
            case "0120" : RPM[WorkingUnitIndex]=WITSVal; break;
        }

        //Assign titles based on number codes.
        WITSTitle=getWITSTitle(WITSCode);
        if (WITSTitle=="") continue;
        WITSLine=WITSTitle + ": " + WITSVal;
        AllWITS[WorkingUnitIndex] += "<option>" + WITSLine + "</option>";
     }


     AllWITS[WorkingUnitIndex] +="</select>";


     BitDepth[WorkingUnitIndex]=Trim(BitDepth[WorkingUnitIndex]);
     if (BitDepth[WorkingUnitIndex]=="0.0" || BitDepth[WorkingUnitIndex]=="0") BitDepth[WorkingUnitIndex]=" ";

}


 ///////////////////////////////////////////////////////////////////////////
   function getWITSTitle(WITSCodeIn) {
       
       var strValueTitle="";

   switch (WITSCodeIn) {

       case "0113": strValueTitle="ROP ft/hr"; break;
       case "0108": strValueTitle="Bit Depth"; break;
       case "0408": strValueTitle="Bit Depth";break;
       case "0116": strValueTitle="Weight On Bit"; break;
       case "0117": strValueTitle="Weight On Bit"; break;
       case "0120": strValueTitle="RPM"; break;
       case "0110": strValueTitle="Hole Depth"; break;
       case "0112": strValueTitle="Block Height"; break;
       case "0114": strValueTitle="Hook Load"; break;
       case "0115": strValueTitle="Hook Load"; break;
       case "0118": strValueTitle="Torque"; break;
       case "0119": strValueTitle="Torque"; break;
       case "0713": strValueTitle="Inclination"; break;
       case "0715": strValueTitle="Azmuth"; break;
       case "0111": strValueTitle="TVD"; break;
       case "0913": strValueTitle="Downhole Pressure"; break;
       case "0818": strValueTitle="Downhole Pressure"; break;
       case "1819": strValueTitle="Downhole Temp"; break;
       case "0139": strValueTitle="WITS Lag Calc"; break;
       case "0824": strValueTitle="Gamma"; break;
       case "0821": strValueTitle="Gamma Lag"; break;
       case "0831": strValueTitle="Porosity 1"; break;
       case "0829": strValueTitle="Porosity 1 Lag"; break;
       case "0834": strValueTitle="Porosity 2"; break;
       case "0832": strValueTitle="Porosity 2 Lag"; break;
       case "0841": strValueTitle="Formation Density"; break;
       case "0839": strValueTitle="Formation Density Lag"; break;
       case "0716": strValueTitle="Magnetic Toolface"; break;
       case "6310": strValueTitle="Magnetic Toolface"; break;
       case "6339": strValueTitle="Magnetic Toolface"; break;
       case "0722": strValueTitle="Toolface Threshold"; break;
       case "0717": strValueTitle="Gravity Toolface"; break;
       case "6311": strValueTitle="Gravity Toolface"; break;
       case "6340": strValueTitle="Gravity Toolface"; break;
       case "0813": strValueTitle="Resistivity 1 Lag"; break;
       case "0816": strValueTitle="Resistivity 1"; break;
       case "0817": strValueTitle="Resistivity 2 Lag"; break;
       case "0820": strValueTitle="Resistivity 2"; break;
       case "0140": strValueTitle="WITS Gas"; break;
       case "1226": strValueTitle="Gas Specific Gravity"; break;
       case "1212": strValueTitle="Methane C1"; break;
       case "1213": strValueTitle="Ethane C2"; break;
       case "1214": strValueTitle="Propane C3"; break;
       case "1215": strValueTitle="IsoButane IC4"; break;
       case "1216": strValueTitle="Butane NC4"; break;
       case "1218": strValueTitle="Pentane NC5"; break;
       case "1217": strValueTitle="IsoPentane IC5"; break;
       case "1219": strValueTitle="NeoPentane IC5"; break;
       case "1220": strValueTitle="IsoHexane NC6"; break;
       case "1221": strValueTitle="Hexane NC6"; break;
       case "1223": strValueTitle="Acetylene"; break;
       case "1222": strValueTitle="WITS CO2"; break;
       case "1225": strValueTitle="WITS O2"; break;
       case "1826": strValueTitle="WITS H2S"; break;
       case "0141": strValueTitle="WITS H2S"; break;
       case "1736": strValueTitle="Nitrogen Rate"; break;
       case "1815": strValueTitle="Nitrogen Pressure In"; break;
       case "1821": strValueTitle="Hydrocarbon Flow"; break;
       case "1828": strValueTitle="Total Gas Return"; break;
       case "1827": strValueTitle="Nitrogen Volume In"; break;
       case "1829": strValueTitle="Nitrogen Volume Out"; break;
       case "1705": strValueTitle="Cement Date"; break;
       case "1706": strValueTitle="Cement Time"; break;
       case "1712": strValueTitle="Cement Pump Pressure"; break;
       case "1716": strValueTitle="Cement Slurry Rate"; break;
       case "1719": strValueTitle="Slurry Density"; break;
       case "1728": strValueTitle="Cement Stage Volume"; break;
       case "1734": strValueTitle="Cement Water Rate"; break;
       case "1830": strValueTitle="Water Out"; break;
       case "1831": strValueTitle="Water Nozzle"; break;
       case "1820": strValueTitle="Condensate Out"; break;
       case "1735": strValueTitle="Annulus Pressure"; break;
       case "1816": strValueTitle="UBD Flow Pressure"; break;
       case "1817": strValueTitle="UBD Flow Temp"; break;
       case "0122": strValueTitle="Casing Pressure"; break;
       case "0121": strValueTitle="Standpipe Pressure"; break;
       case "0414": strValueTitle="Standpipe Pressure"; break;
       case "0123": strValueTitle="Pump 1 SPM"; break;
       case "0124": strValueTitle="Pump 2 SPM"; break;
       case "0125": strValueTitle="Pump 3 SPM"; break;
       case "0143": strValueTitle="Pump 1 Total Strokes"; break;
       case "0144": strValueTitle="Pump 2 Total Strokes"; break;
       case "0145": strValueTitle="Pump 3 Total Strokes"; break;
       case "1115": strValueTitle="Mudtank Volume 1"; break;
       case "1116": strValueTitle="Mudtank Volume 2"; break;
       case "1116": strValueTitle="Mudtank Volume 3"; break;
       case "1118": strValueTitle="Mudtank Volume 4"; break;
       case "1119": strValueTitle="Mudtank Volume 5"; break;
       case "1120": strValueTitle="Mudtank Volume 6"; break;
       case "1121": strValueTitle="Mudtank Volume 7"; break;
       case "1122": strValueTitle="Mudtank Volume 8"; break;
       case "1129": strValueTitle="Trip Tank Vol"; break;
       case "0128": strValueTitle="Flow"; break;
       case "1110": strValueTitle="Total Mud Vol"; break;
       case "1111": strValueTitle="Total Mud Vol"; break;
       case "0130": strValueTitle="Total Pump Output"; break;
       case "0137": strValueTitle="Total Pump Strokes"; break;
       case "0150": strValueTitle="Total Pump Disp"; break;
       case "0142": strValueTitle="Total Pump Disp"; break;
       case "0127": strValueTitle="Mud GainLoss"; break;
       case "1724": strValueTitle="Event Number"; break;
       case "1984": strValueTitle="WITS System Info"; break;
       default: strValueTitle="UNKNOWN";
     }

    strValueTitle= WITSCodeIn + " " + strValueTitle;

     return strValueTitle;

   }
   
//////////////////////////////////////////////////////////////////////////////

function GetStatusDisplayString(CodeIn, UnitIndex) {
    
    
    var strResult="";
    var strTemp;
    var i;

       //status code 998 for when an xml file is present,
       //but there is no bloodhound packet in the file.

        if (CodeIn==undefined) CodeIn="998";
        if (CodeIn=="undefined") CodeIn="998";  //yes, it happens.

        var CodeList=CodeIn.split(" ");

        for (i=0;i<=CodeList.length-1;i++) {
            var s=Trim(CodeList[i]);


            switch (s) {
                case "0"   : StatusCellClass = "StatusOK";       strTemp= "OK"; break;
                case "1"   : StatusCellClass = "StatusError";    strTemp= "High Line Pressure"; break;
                case "2"   : StatusCellClass = "StatusError";    strTemp= "Blocked Line"; break;
                case "3"   : StatusCellClass = "StatusError";    strTemp= "High Detector Volts"; break;
                case "4"   : StatusCellClass = "StatusError";    strTemp= "Low Detector Volts"; break;
                case "5"   : StatusCellClass = "StatusError";    strTemp= "High Flow Rate"; break;
                case "6"   : StatusCellClass = "StatusError";    strTemp= "Low Flow Rate"; break;
                case "7"   : StatusCellClass = "StatusError";    strTemp= "Low Rig Voltage"; break;
                case "9"   : StatusCellClass = "StatusError";    strTemp= "High Amps"; break;
                case "10"  : StatusCellClass = "StatusError";    strTemp= "High Temperature"; break;
                case "11"  : StatusCellClass = "StatusError";    strTemp= "Low Temperature"; break;
                case "12"  : StatusCellClass = "StatusError";    strTemp= "High Gas Units"; break;
                case "13"  : StatusCellClass = "StatusWarmup";   strTemp= "Warming Up"; break;
                case "14"  : StatusCellClass = "StatusShutdown"; strTemp= "Shutting Down"; break;
                case "15"  : StatusCellClass = "StatusError";    strTemp= "Geolograph Failure"; break;
                case "16"  : StatusCellClass = "StatusError";    strTemp= "CG Pressure Low"; break;
                case "17"  : StatusCellClass = "StatusError";    strTemp= "HIGH H2S"; break;
                case "18"  : StatusCellClass = "StatusError";    strTemp= "Exhaust Blocked"; break;
                case "255" : StatusCellClass = "StatusError";    strTemp= "Service Required"; break;
                case "998" : StatusCellClass = "StatusOffline";  strTemp= "(offline)"; break;
                case "999" : StatusCellClass = "StatusError";    strTemp= "Unknown Unit ID"; IsKnownUnit[UnitIndex]=false; break;
                default    : StatusCellClass = "StatusError";    strTemp= "Unlisted Error: " + s;
            }
            
            if (i<CodeList.length-1) strTemp += "<br>";
            strResult += strTemp;
        }

        //If the unit is offline but not unlisted, indicate so in status
        var intLocalUptime=UnitUptime[UnitIndex] * 1;  //force to treat as number
        if (s!="" && intLocalUptime==0 && iBallErrorNumber[UnitIndex]!="999"  && iBallErrorNumber[UnitIndex]!="998") {
            StatusCellClass = "StatusOffline";
            if (strResult == "OK"){
                strResult = "offline";
            }else {
              strResult += "<br> offline";
            }
        }
         
     return strResult;       

}


//////////////////////////////////////////////////////////////////////////////

function RefreshDisplay() {
  
    var strOutputTable= BuildOutputTable();
    document.getElementById("MainTable").innerHTML=strOutputTable;
    

}



///////////////////////////////////////////////////////////////////////////////
function AddToolTip(DisplayText, ToolTipText,indexIn){
    
    var result;
    
    FixedMessage[indexIn]=ToolTipText;
    
    result="<span class=\"ttip1\" onmouseover=if(ToolTip1)ToolTip1.Show(event,FixedMessage[" + indexIn + "])";
    result +=" onmouseout=if(ToolTip1)ToolTip1.Hide(event)>";
    result +=DisplayText;
    result +="</span>";
    return result;

}




////////////////////////////////////////////////////////////////////////////////

function AddToolTip2(DisplayText, indexIn){
    
    var result;
    var tblOut;
    var StatusMsg;

    var strGasDisplay;
    var strBitDepthDisplay;
    var strBitDepthCaption;

    var strHoleDepthDisplay;
    var ROPMinFtDisplay;
    var ROPFtHrDisplay;

    StatusMsg=" ";
    StatusMsg=Trim(GetStatusDisplayString(Trim(iBallErrorNumber[indexIn]), indexIn));


    if (StatusMsg=="OK"){
        StatusMsg="<font color=\"green\"><b>None</b></font>";
    
    } else {
        StatusMsg="<font color=\"red\"><b>" + StatusMsg + "</b></font>";
    }




    ROPMinFtDisplay= ROP[indexIn];
    ROPFtHrDisplay =ROPFtHr[indexIn];
    strHoleDepthDisplay=HoleDepth[indexIn];


   //Color code gas units.
    try {
        //Force Gas Units to be treated as a number.
         GasUnits[indexIn]= GasUnits[indexIn] * 1;

         if (GasUnits[indexIn]<=ELEVATEDGASTHRESHOLD)
             strGasDisplay="<font color=\"#00FF00\">" + GasUnits[indexIn] + "</font>";
         if (GasUnits[indexIn]>ELEVATEDGASTHRESHOLD)
             strGasDisplay="<font color=\"yellow\">" + GasUnits[indexIn] + "</font>";
         if (GasUnits[indexIn]>ALERTGASTHRESHOLD)
             strGasDisplay="<font color=\"red\">" + GasUnits[indexIn] + "</font>";
    } catch (e) {
        strGasDisplay=GasUnits[indexIn];
    }



    try {

        //force hole depth and bit depths to be treated as numbers.
        HoleDepth[indexIn]=HoleDepth[indexIn] * 1;
        BitDepth[indexIn]=BitDepth[indexIn] / 1;

        if (BitDepth[indexIn]<1){
             strBitDepthCaption="Bit Depth";
            strBitDepthDisplay="&nbsp;";

        } else {
            if (BitDepth[indexIn]< (HoleDepth[indexIn] - BITDEPTHMINDELTA)){
                strBitDepthCaption="(Off Bottom) Bit Depth</font>";
                strBitDepthDisplay="<font color=\"#F87217\">" + BitDepth[indexIn] +"</font>";
            } else {
                strBitDepthCaption="Bit Depth";
                strBitDepthDisplay=BitDepth[indexIn];
                if (isNaN(strBitDepthDisplay)) strBitDepthDisplay="&nbsp;";
            }
        }

    } catch (e) {
        strBitDepthCaption="Bit Depth";
        strBitDepthDisplay=trim(BitDepth[indexIn]);
        if (strBitDepthDisplay==".0") strBitDepthDisplay="&nbsp;";
    }


   
    
    

    
tblOut="<br><center>";
tblOut += "<table bgcolor=\"LightGrey\" width=\"720\" border=\"7\" cellpadding=0 height=\"310\">";
tblOut +=   "<tr>";
tblOut +=		"<td width=\"120\" rowspan=\"2\" height=\"180\" valign=\"top\" align=\"center\">";
tblOut +=			" <table bgcolor=\"#150517\" Border=\"1\" cellpadding=3 width=\"100%\" height=\"350\">";
tblOut +=			  "<tr><td align=\"center\"><font color=\"#FFFFFF\" size=\"1\" face=\"arial\"><b>Gas Units</b></font>   <br><font color=\"#FFFFFF\" size=\"6\" face=\"arial\"><b id=\"GasUnits\">"   + strGasDisplay           + "</font></b>&nbsp;</td></tr>";
tblOut +=			  "<tr><td align=\"center\"><font color=\"#FFFFFF\" size=\"1\" face=\"arial\"><b>Hole Depth</b></font> <br><font color=\"#FFFFFF\" size=\"6\" face=\"arial\"><b id=\"HoleDepth\">"  + strHoleDepthDisplay      + "</font></b>&nbsp;</td></tr>";
tblOut +=			  "<tr><td align=\"center\"><font color=\"#FFFFFF\" size=\"1\" face=\"arial\"><b>" + strBitDepthCaption +"</b></font>   <br><font color=\"#FFFFFF\" size=\"6\" face=\"arial\"><b id=\"BitDepth\">"   + strBitDepthDisplay       + "</font></b>&nbsp;</td></tr>";
tblOut +=			  "<tr><td align=\"center\"><font color=\"#FFFFFF\" size=\"1\" face=\"arial\"><b>ROP min/ft</b></font>  <br><font color=\"#FFFFFF\" size=\"6\" face=\"arial\"><b id=\"ROP\">"        +  ROPMinFtDisplay            + "</font></b>&nbsp;</td></tr>";
tblOut +=			  "<tr><td align=\"center\"><font color=\"#FFFFFF\" size=\"1\" face=\"arial\"><b>ROP ft/hr</b></font>   <br><font color=\"#FFFFFF\" size=\"6\" face=\"arial\"><b id=\"ROPFtHrBig\">" + ROPFtHrDisplay       + "</font></b>&nbsp;</td></tr>";
tblOut +=			  "<tr><td align=\"center\"><font color=\"#FFFFFF\" size=\"1\" face=\"arial\"><b>Lag Depth</b></font>   <br><font color=\"#00FFFF\" size=\"6\" face=\"arial\"><b id=\"LagDepth\">"   + iBallLagDepth[indexIn]  + "</font></b>&nbsp;</td></tr>";
tblOut +=			 "</table>";
tblOut +=		"</td>";
tblOut +=		"<td height=\"29\" align=\"left\" >";
tblOut +=            "<table  bgcolor=\"LightGrey\" border=\"0\" cellpadding=\"0\">";
tblOut +=				"<tr>";
tblOut +=				  "<td align=\"left\"><font size=\"3\" id=\"UnitID\"><b>&nbsp;&nbsp;Unit ID: " + UnitID[indexIn] + "&nbsp;&nbsp;&nbsp;&nbsp;Job #: " + JobNumber[indexIn] + "</b></font></td>";
tblOut +=				"</tr>";
tblOut +=			"</table>";
tblOut +=		"</td>";
tblOut +=		"<td width=\"278\" rowspan=\"2\" height=\"190\" valign=\"top\" align=\"center\" bgcolor=\"#eeeeee\" >";
tblOut +=			    "<font id=\"WITSDisplayString\">"+ AllWITS[indexIn] + "</font>";
tblOut +=		"</td>";
tblOut +=    "</tr>";
tblOut +=    "<tr>";
tblOut +=    "<td width=\"350\" height=\"157\" align=\"center\">";
tblOut +=	  "<table bgcolor=\"LightGrey\" border=\"1\" cellpadding=1 height=\"255\">";
tblOut +=	  "<tr>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">%CO2</font><br><font size=\"1\" face=\"arial\" id=\"CO2\">" + CO2[indexIn] + "</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Time</font><br><font size=\"1\" face=\"arial\" id=\"iBallTime\">"+ iBallTime[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Date</font><br><font size=\"1\" face=\"arial\" id=\"iBallDate\">"+ iBallDate[indexIn] +"</font></td>";
tblOut +=	  "</tr>";
tblOut +=	  "<tr>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">%O2</font><br><font size=\"1\" face=\"arial\" id=\"O2\">"+ O2[indexIn] +"</font></td>";
tblOut +=       "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Sample Vac</font><br><font size=\"1\" face=\"arial\" id=\"SampleVac\">"+ SampleVac[indexIn] +"</font></td>";
tblOut +=	    "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Internal Temp</font><br><font size=\"1\" face=\"arial\" id=\"InternalTemp\">"+ InternalTemp[indexIn] +"</font></td>";
tblOut +=	  "</tr>";
tblOut +=	  "<tr>";
tblOut +=	    "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">H2S PPM</font><br><font size=\"1\" face=\"arial\" id=\"H2S\">"+ H2S[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Sample LPH</font><br><font size=\"1\" face=\"arial\" id=\"SampleVol\">"+ SampleVol[indexIn] +"</font></td>";
tblOut +=       "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Attenuation</font><br><font size=\"1\" face=\"arial\" id=\"Attenuation\">"+ Attenuation[indexIn] +"</font></td>";
tblOut +=     "</tr>";
tblOut +=      "<tr>";
tblOut +=        "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">ROP ft/hr</font><br><font size=\"1\" face=\"arial\" id=\"ROPFtHr\">"+ ROPFtHr[indexIn] +"</font></td>";
tblOut +=		 "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Error Number</font><br><font size=\"1\" face=\"arial\" id=\"iBallErrorNumber\">"+ iBallErrorNumber[indexIn] +"</font></td>";
tblOut +=		 "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Internal Volts</font><br><font size=\"1\" face=\"arial\" id=\"InternalVolts\">"+ InternalVolts[indexIn] +"</font></td>";
tblOut +=	  "</tr>";
tblOut +=	  "<tr>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Pri Voltage</font><br><font size=\"1\" face=\"arial\" id=\"PriVoltage\">"+ PriVoltage[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Sec Voltage</font><br><font size=\"1\" face=\"arial\" id=\"SecVoltage\">"+ SecVoltage[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">H2S Voltage</font><br><font size=\"1\" face=\"arial\" id=\"H2SVoltage\">"+ H2SVoltage[indexIn] +"</font></td>";
tblOut +=	  "</tr>";
tblOut +=      "<tr>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">CG Voltage</font><br><font size=\"1\" face=\"arial\" id=\"CGVoltage\">"+ CGVoltage[indexIn] +"</font></td>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">CG Test ID</font><br><font size=\"1\" face=\"arial\" id=\"CGTestID\">"+ CGTestID[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">RSSI</font><br><font size=\"1\" face=\"arial\" id=\"RSSI\">"+ RSSI[indexIn] +"</font></td>";
tblOut +=     "</tr>";
tblOut +=      "<tr>";
tblOut +=       "<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Rig Voltage</font><br><font size=\"1\" face=\"arial\" id=\"RigVoltage\">"+ RigVoltage[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Rig Frequency</font><br><font size=\"1\" face=\"arial\" id=\"RigFrequency\">"+ RigFrequency[indexIn] +"</font></td>";
tblOut +=		"<td width=\"116\" align=\"center\" height=\"28\"><font size=\"1\" face=\"arial\">Extractor Amps</font><br><font size=\"1\" face=\"arial\" id=\"ExtractorAmps\">"+ ExtractorAmps[indexIn] +"</font></td>";
tblOut +=     "</tr>";
tblOut +=      "<tr>";
tblOut +=       "<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Sample Motor%</font><br><font size=\"1\" face=\"arial\" id=\"SampleMotor\">"+ SampleMotor[indexIn] +"</font></td>";
tblOut +=	    "<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">HRMTemp</font><br><font size=\"1\" face=\"arial\" id=\"HRMTemp\">"+ HRMTemp[indexIn] +"</font></td>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Chrom. Prs.</font><br><font size=\"1\" face=\"arial\" id=\"ChromVac\">" + ChromVac[indexIn] + "</font></td>";
tblOut +=	   "</tr>";
tblOut +=      "<tr>";
tblOut +=       "<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Methane</font><br><font size=\"1\" face=\"arial\">"+ C1Gas[indexIn] + "</font></td>";
tblOut +=	    "<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Ethane </font><br><font size=\"1\" face=\"arial\">"+ C2Gas[indexIn] + "</font></td>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Propane</font><br><font size=\"1\" face=\"arial\">"+ C3Gas[indexIn] + "</font></td>";
tblOut +=	   "</tr>";
tblOut +=      "<tr>";
tblOut +=       "<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">IsoButane</font><br><font size=\"1\" face=\"arial\">"+ IC4Gas[indexIn] +"</font></td>";
tblOut +=	    "<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">NButane</font><br><font size=\"1\" face=\"arial\">"+ NC4Gas[indexIn] +"</font></td>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Col. Temp</font><br><font size=\"1\" face=\"arial\">" + ColumnTemp[indexIn] + "</font></td>";
tblOut +=	   "</tr>";
tblOut +=      "<tr>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"11\" colspan=\"2\"><font size=\"1\" face=\"arial\">Error Description</font><br><font size=\"2\" face=\"arial\">" + StatusMsg + "</font></td>";
tblOut +=	  	"<td width=\"116\" align=\"center\" height=\"11\"><font size=\"1\" face=\"arial\">Exhaust Prs.</font><br><font size=\"1\" face=\"arial\">" + ExhaustPressure[indexIn] + "</font></td>";

tblOut +=	   "</tr>";




tblOut +=     "</table>";
tblOut +=   "</td>";
tblOut +=   "</tr>";
tblOut += "</table>";
tblOut += "</center>";

    AllData[indexIn]=tblOut;



      //code to hide the tool tip is in BuildOutputTable.
    result="<span class=\"ttip2\" onmouseover=if(ToolTip2)ToolTip2.Show(event,AllData[" + indexIn + "]) >";
    result +=DisplayText + "</span>";
    
    return result;

}



///////////////////////////////////////////////////////////////////////////

function BuildOutputTable() {

   var strOutputTable="";
   var LocalLeaseName="";
   var LocalBitDepth="";
   var LocalRPM="";
   var LocalWOB="";
   var LocalLastUpdate="";
   var LocalROP="";
   var LocalROPfthr="";
   var LocalGasUnits="";
   var LocalStatusDisplay="";
   var LocalHoleDepth="";
   var LocalUnitID="";
   var LocalSuck="";
   var LocalUnitUptime="";
   
   var CommonCellClass="";
   var BitDepthCellClass="";
   var UptimeCellClass="";
   var GassCellClass="";

   var strTemp="";

   var intLocalUptime=0;

   
   
   //TDC = Table Detail Clear. When the mouse
   // enters any of the fields other than unit ID or status
   //then hide the detail popup.

   var TDC= "onmouseover=if(ToolTip2)ToolTip2.Hide(event)";
   
   
   strOutputTable="<table border=\"3\" cellpadding= \"1\" width=\"100%\" ";
       strOutputTable +="class=\"MainTable\" "
       strOutputTable +=">"
       strOutputTable +="<tr>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Unit","Bloodhound Serial Number",0);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Status","Status of Unit",1);
       strOutputTable +="</font></td>";
       if (ShowUptimeColumn) {
          strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
          strOutputTable += AddToolTip("Uptime","Percent of time the Bloodhound was able to connect to server",2);
          strOutputTable +="</font></td>";
       }
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Lease","Lease Name of the Assigned Well",3);
       strOutputTable +="</font></td>";

        if (ShowLastUpdateColumn){
           strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
           strOutputTable += AddToolTip("Updated","Date/Time when the Bloodhound Last Sent Valid Data and number of days since then",4);
           strOutputTable +="</font></td>";
       }
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Gas"," Gas Units.<br>10,000 Units=100% Gas",5);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Hole","Drill Hole Depth",6);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Bit","Drill Bit Depth",7);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("MIN/FT","Drill Rate of Penetration",8);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("RPM","Drill Pipe Revolutions Per Minute",9);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("WOB","Weight on Drill Bit",10);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("ATT","Bloodhound Gas Sensor Attenuation Setting",11);
       strOutputTable +="</font></td>";
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("RSSI","Bloodhound Signal Strength",12);
       strOutputTable +="</font></td>";

       if (ShowExAmpColumn) {
          strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
          strOutputTable += AddToolTip("ExAmps","Extractor Current Draw",13);
          strOutputTable +="</font></td>";
       }
       strOutputTable +="<td class=\"TableHead\">" +  strTableFontSize;
       strOutputTable += AddToolTip("Vac/LPH/Mot","Sample Line Vacuum mmHg, Sample Line Volume LPH, Sample Motor Load %",14);
       strOutputTable +="</font></td>";

     strOutputTable +="</tr>";

     var BL;
     if (FirstPass) {
         BL=WorkingUnitIndex;
     }else{
         BL=UnitID.length-1;
     }

     for (i=0;i<=BL;i++)  {

         if (iBallErrorNumber[i]==undefined) iBallErrorNumber[i]="998";
         
         strTemp=Trim(iBallErrorNumber[i]);
         LocalStatusDisplay=GetStatusDisplayString(strTemp, i);

         intLocalUptime=UnitUptime[i] * 1;

         if (HideOffline && intLocalUptime==0 && iBallErrorNumber[i]!="999") continue;
         if (iBallErrorNumber[i]=="999" && !IsDebugMode) continue;

         LocalLeaseName=LeaseName[i];
         if (LocalLeaseName==undefined) LocalLeaseName=" ";

         if (LocalLeaseName.length>MAXLEASENAMELENGTH) LocalLeaseName=LocalLeaseName.substring(0,MAXLEASENAMELENGTH-1);

         if (BitDepth[i]==undefined) BitDepth[i]="&nbsp;";

         LocalBitDepth=Trim(BitDepth[i]);
         LocalHoleDepth=Trim(HoleDepth[i]);
         if (WOB[i]==undefined) {
             LocalWOB[i]="&nbsp;";
         } else {
           LocalWOB=WOB[i];
         }
         LocalRPM=RPM[i];


         
         if (LocalRPM=="") LocalRPM="&nbsp;";
         if (Trim(LocalWOB)=="") LocalWOB="&nbsp;";
         if (LocalBitDepth=="") {
             LocalBitDepth="&nbsp;";
             BitDepth[i]="&nbsp;";
         }



         if (!isNaN(ROP[i])) {
             LocalROP=Math.round(ROP[i]*10)/10;
             ROP[i]=LocalROP;
         } else {
             LocalROP="&nbsp;";
         }


         LocalROPfthr=Math.round(ROPFtHr[i]*10)/10;
         ROPFtHr[i]=LocalROPfthr;


         if (!isNaN(GasUnits[i])) {
            LocalGasUnits=Math.round(GasUnits[i]*10)/10;
            GasUnits[i]=LocalGasUnits;
        }else {
              LocalGasUnits="&nbsp;";
         }


         //This line shouldn't be needed
         if (LocalRPM=="&nbsp;" && LocalBitDepth=="&nbsp;")  LocalBitDepth="&nbsp;";


         LocalLastUpdate=ConvertTimeToString(LastUpdate[i]);
         LocalUnitUptime=UnitUptime[i];


          if ((WebPageAddr[i]=="") || (WebPageAddr[i]==" ") || (WebPageAddr[i]==undefined))  {
               LocalUnitID=UnitID[i];
          } else {
              var s= Trim(WebPageAddr[i].toLowerCase());

              if (s.indexOf("http://") < 0) s ="\"http://" + s;
              LocalUnitID="<a href=" + s +" target=\"_blank\">" + UnitID[i] + "</a>";

          }


         CommonCellClass="ActiveCell";

           if (isNaN(LocalBitDepth) || isNaN(LocalHoleDepth) || LocalBitDepth=="&nbsp;" || LocalBitDepth==""){
              BitDepthCellClass="ActiveCell";
           }else {
           // Do the -0, /1 and *1 operators to force MATH comparison as opposed
           //to STRING comparison
               if ((LocalHoleDepth-0)>=((LocalBitDepth/1) + (BITDEPTHMINDELTA*1))) {
                  BitDepthCellClass="BitOffBottom";
               }else{
                  BitDepthCellClass="ActiveCell";
              }
           }

           if (intLocalUptime!=100.0) {
                UptimeCellClass="GasElevated";
           } else {
                UptimeCellClass="ActiveCell";
           }

           if (intLocalUptime==0) UptimeCellClass="GasElevated";

           var ttclear=true;
           if (iBallErrorNumber[i]!="999" && iBallErrorNumber[i]!="998") ttclear = false;
           if (!ttclear)  LocalUnitID=AddToolTip2(LocalUnitID,i);


           if (LocalGasUnits < ELEVATEDGASTHRESHOLD) GassCellClass="GasOK";
           if (LocalGasUnits >= ELEVATEDGASTHRESHOLD) GassCellClass="GasElevated";
           if (LocalGasUnits >= ALERTGASTHRESHOLD) GassCellClass="GasAlert";

          if (!IsDefined(LocalRPM)) LocalRPM="&nbsp";
          if (isNaN(LocalBitDepth)) LocalBitDepth="&nbsp;";
          if (isNaN(LocalHoleDepth)) LocalHoleDepth="&nbsp;";

          if (Trim(LocalUnitUptime)=="") LocalUnitUptime="&nbsp;";
          if (Trim(LocalLeaseName)=="") LocalLeaseName="&nbsp;";
          if ((Trim(Attenuation[i])=="") ||(Attenuation[i]==undefined)) Attenuation[i]="&nbsp;";
          if ((Trim(ExtractorAmps[i])=="") ||(ExtractorAmps[i]==undefined)) ExtractorAmps[i]="&nbsp;";

          if ((Trim(RSSI[i])=="") || (RSSI[i]==undefined)) RSSI[i]="&nbsp;";
          if (Trim(LocalHoleDepth)=="") LocalHoleDepth="&nbsp;";

          if ((Trim(SampleVac[i])=="") || (SampleVac[i]==undefined)) SampleVac[i]="&nbsp;";
          if ((Trim(SampleVol[i])=="") || (SampleVol[i]==undefined)) SampleVol[i]="&nbsp;";
          if ((Trim(SampleMotor[i])=="") || (SampleMotor[i]==undefined)) SampleMotor[i]="&nbsp;";
         
           LocalSuck=SampleVac[i] + " / " + SampleVol[i] + " / " + SampleMotor[i];

           strOutputTable +="<tr> ";

           //have a mouseover event on the UnitID column remove
           //a detail view (tooltip2) only if the unit is unknown or
           //offline due to a missing bloodhound packet.
           strOutputTable += "<td class=\"" +  CommonCellClass
           if (!ttclear){
              strOutputTable +="\">";
           } else {
              strOutputTable += "\"" + TDC + ">";
           }
           strOutputTable += strTableFontSize + LocalUnitID +  "</font></td>";


           strOutputTable += "<td class=\"" +  StatusCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalStatusDisplay + "</font></td>";
           if (ShowUptimeColumn) {
             strOutputTable += "<td class=\"" +  UptimeCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalUnitUptime +  "</font></td>";
           }
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize +  LocalLeaseName +  "</font></td>";
           if (ShowLastUpdateColumn){
               strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize +  LocalLastUpdate +  "</font></td>";
           }
           strOutputTable += "<td class=\"" +  GassCellClass     + "\"" + TDC + ">"+ strTableFontSize + LocalGasUnits  +  "</font></td>";
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalHoleDepth +  "</font></td>";
           strOutputTable += "<td class=\"" +  BitDepthCellClass + "\"" + TDC + ">"+ strTableFontSize + LocalBitDepth +  "</font></td>";
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalROP +  "</font></td>";
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalRPM +  "</font></td>";
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalWOB +  "</font></td>";
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + Attenuation[i] +  "</font></td>";
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + RSSI[i] +  "</font></td>";
           if (ShowExAmpColumn) {
              strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + ExtractorAmps[i] +  "</font></td>";
           }   
           strOutputTable += "<td class=\"" +  CommonCellClass   + "\"" + TDC + ">"+ strTableFontSize + LocalSuck +  "</font></td>";
           strOutputTable += "</tr>";
          
    }  
    strOutputTable +="</table>";


    return(strOutputTable);

}



 ///////////////////////////////////////////////////////////////////////////
   function InitDataRequest() {

   	if (GettingData) return false;

   	GettingData=true;
    UnitCount=-1;
    WorkingUnitIndex=-1;

   	XMLDocIn="";
   	LastAttemptInterval=0;

        if (window.XMLHttpRequest) {
        	xhr= new XMLHttpRequest();     //Modern Browsers
        }else{
           if (window.ActiveXObject)  {    //IE
              try {
                xhr= new ActiveXObject("Microsoft.XMLHTTP");   
              } catch(e) {
                if (IsDebugMode) {
                   document.getElementById("ErrorMessage").innerHTML=" Error Message: Unable to Create Active X XMLHttpRequest Object<br>"; 
	     	       errmsg=errmsg + e.message + "<br>";
	     	       document.getElementById("xhrErrorMessage").innerHTML=errmsg;
	      	    }
              }
           }
        }

       if (!xhr){
          if (IsDebugMode) document.getElementById("ErrorMessage").innerHTML="Cannot create XMLHttpRequest<br>";
	      if (IsDebugMode) document.getElementById("iBallInfoDisplay").innerHTML="Cannot create xhr object.<br>";
	      GettingData=false;
	      return false;
       }

     xhr.onreadystatechange=HandleServerResponse;
   
       return true;
   }


 //////////////////////////////////////////////////////////////////////////

 function RequestXMLFile(){

   var strDisplay;

     if (RequestPending) return;
      //If XML file isn't present don't bother asking for it
      if (!IsKnownUnit[WorkingUnitIndex]) return;
      RequestPending=true;
      try {
            //add a "?" and and a unique string to the end
             //of the server request to avoid caching problems.
            RequestID=CreateGUID();
            var FullRequestString= UnitID[WorkingUnitIndex] + "_UnitData.xml?RequestID=" + RequestID;
            if (IsDebugMode) {
                strDisplay="<font color=\"RED\">RequestID:</font>&nbsp;&nbsp;" + RequestID + "<br>";
                document.getElementById("RequestID").innerHTML= strDisplay;
                document.getElementById("RequestString").innerHTML="<font color=\"RED\">Request String:</font> " + FullRequestString + "<br>";
            }
 
 
                //IE 7 requires that to reuse an xmlhttp request object
                //you have to reset the onreadystatechange property after
                //doing the open.
             if (window.ActiveXObject)  {
                 xhr.open("GET",FullRequestString,true);
                 xhr.onreadystatechange=HandleServerResponse;
                 xhr.send(null);
             } else {
                 xhr.open("GET",FullRequestString,true);
                 xhr.send(null);
             }
       
      }catch (e){
        if (IsDebugMode) {
            document.getElementById("ErrorMessage").innerHTML="Cannot open Connection to Server<br>";
            errmsg=errmsg + e.message + "<br>";
            document.getElementById("xhrErrorMessage").innerHTML=errmsg +"<br>";
            document.getElementById("iBallInfoDisplay").innerHTML="Cannot Connect To Server-- Open xhr fail.<br>";
            RequestPending=false;
        }

      }
     

 }
////////////////////////////////////////////////////////////////////////////
function HandleServerResponse(){
    var strDisplay;
    var strResponse;
    var strExtraInfo;
    var strTemp;

       if (!xhr.readyState==4) return;

       try {
          strResponse=xhr.status;
       } catch (e) {
          return;
       }

        switch (strResponse) {
            case "200": strExtraInfo="200 -- OK"; break;
            case "204": strExtraInfo="204 -- No Content"; break;
            case "206": strExtraInfo="206 -- Partial Content"; break;
            case "400": strExtraInfo="400 -- Bad Request"; break;
            case "401": strExtraInfo="401 -- Unauthorized"; break;
            case "403": strExtraInfo="403 -- Forbidden"; break;
            case "404": strExtraInfo="404 -- File Not Found";break;
            case "408": strExtraInfo="408 -- Request Timeout"; break;
            case "414": strExtraInfo="414 -- Request-URI Too Long"; break;
            case "500": strExtraInfo="500 -- Internal Server Error"; break;
            case "503": strExtraInfo="503 -- Service Unavailable"; break;
            default : strExtraInfo= "Status Code: " + ServerReturnCode;
        }

        if (strResponse!="200"){
             IsKnownUnit[WorkingUnitIndex]=false;
             iBallErrorNumber[WorkingUnitIndex]="999";
        } else {
            IsKnownUnit[WorkingUnitIndex]=true;
        }
        UnitCount++;

        if (IsDebugMode) {
         strDisplay="<font color=\"RED\">Server Returns:</font> " + strExtraInfo + "<br>";
          document.getElementById("ServerMessage").innerHTML= strDisplay;
        }

        

        if (window.ActiveXObject)  {  //IE
          XMLDocIn = new ActiveXObject("Microsoft.XMLDOM");
          strTemp=xhr.responseText;
          XMLDocIn.loadXML(strTemp);
        } else {  //modern browsers
            strTemp=xhr.responseText;
            XMLDocIn=(new DOMParser()).parseFromString(strTemp, "text/xml");
        }

        var strTimeIn=GetCurrentTimeAsString();
        if (IsDebugMode) document.getElementById("LastServerResponse").innerHTML="<font color=\"RED\">Most Recent Server Response:</font> " + strTimeIn +"<br>";
        if (ParseXMLData()){
               if (IsDebugMode) {
                  strTimeIn=GetCurrentTimeAsString();
                  document.getElementById("LastValidServerResponse").innerHTML="<font color=\"RED\">Most Recent Good Server Response:</font> " + strTimeIn +"<br>";
                  document.getElementById("XMLFileCreated").innerHTML="<font color=\"RED\">XML Response File Generated:</font> " + XMLFileCreated +"<br>";
               }
               if (NewDataIn){
                   if (IsDebugMode) document.getElementById("LastNewServerResponse").innerHTML="<font color=\"RED\">Most Recent New Server Response:</font> " + strTimeIn +"<br>";
                   DataAge=0;
              }
        }

     //If this is the first load/display cycle, we will
     //let the table "grow" as the data comes in.
    if (FirstPass) RefreshDisplay();
    
    RequestPending=false;

}


   //////////////////////////////////////////////////////////////////////////
function ParseXMLData() {

    if (XMLDocIn==null) {
       NewDataIn=false;
       return false;
   }


   var XMLStringIn =XMLToHTML(XMLDocIn);
   var UptimeIn;
   var LastPostTimeIn;
   var BHPacketIn;
   var WITSPacketIn;
   var WebPageIn;


   try {
       WebPageIn=  " " + XMLDocIn.getElementsByTagName("WebPage")[0].childNodes[0].nodeValue;
       WebPageAddr[WorkingUnitIndex]= WebPageIn;
   } catch (e) {
       WebPageAddr[WorkingUnitIndex]= " ";
   }


   try {
       UptimeIn = " " + XMLDocIn.getElementsByTagName("Uptime")[0].childNodes[0].nodeValue;
       UnitUptime[WorkingUnitIndex]=UptimeIn;
   } catch (e) {
       UnitUptime[WorkingUnitIndex]=" ";
   }

    try {
       LastPostTimeIn=  " " + XMLDocIn.getElementsByTagName("LastPostTime")[0].childNodes[0].nodeValue;
       LastUpdate[WorkingUnitIndex]=LastPostTimeIn;
       XMLFileCreated=LastPostTimeIn;
   } catch (e) {
        LastUpdate[WorkingUnitIndex]=" ";
   }

    // We're OK if WITS data is missing.
    try {
        WITSPacketIn=  " " + XMLDocIn.getElementsByTagName("WITSPacket")[0].childNodes[0].nodeValue;
        WITSRawPacket[WorkingUnitIndex]=WITSPacketIn;
    }catch (e){
       WITSPacketIn=" ";
    }


    try {
       BHPacketIn=  " " + XMLDocIn.getElementsByTagName("BHPacket")[0].childNodes[0].nodeValue;
       iBallRawPacket[WorkingUnitIndex]=BHPacketIn;
    } catch (e) {
       NewDataIn=false;
       iBallRawPacket[WorkingUnitIndex]=" ";
       return false;
    }
     NewDataIn=true;



    ParseBloodhoundData();
    ParseWITSData();

      if (IsDebugMode) {
         document.getElementById("SessionID").innerHTML= "<font color=\"RED\">Session ID:</font> " + SessionID + "<br>";
         document.getElementById("SessionRefresh").innerHTML="<font color=\"RED\">Session Refresh:</font> " + LastPostTimeIn +"<br>";
         document.getElementById("UnitCount").innerHTML="<font color=\"RED\">Recognized Units:</font> " + UnitCount +"<br>";
         document.getElementById("XMLData").innerHTML="<br><font color=\"RED\"><u>XML Data:</u></font><br>" + XMLStringIn  +"<br>" ;
     }

    return true;

}



///////////////////////////////////////////////////////////////////////////
function FinishOutDataRequest(){
     LastAttemptInterval=0;
     strTimeIn=GetCurrentTimeAsString();
     if (IsDebugMode) document.getElementById("LastServerRequest").innerHTML="<font color=\"RED\">Most Recent Server Request:</font> " + strTimeIn + "<br>";

     FirstPass=false;
     GettingData=false;
     RefreshDisplay();
}


   
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

function ToolTipObject(id,isAnimated,aniSpeed)
// Free for any type of use so long as original notice remains unchanged.
// Report errors to feedback@ashishware.com
//Copyrights 2006, Ashish Patil , ashishware.com
//////////////////////////////////////////////////////////////////////////

{ var isInit = -1;
  var div,divWidth,divHeight;
  var xincr=10,yincr=10;
  var animateToolTip =false;
  var html;
  
  function Init(id)
  {
   div = document.getElementById(id);
   if(div==null) return;
   
   if((div.style.width=="" || div.style.height==""))
   {alert("Both width and height must be set");
    return;}
   
   divWidth = parseInt(div.style.width);
   divHeight= parseInt(div.style.height);
   if(div.style.overflow!="hidden")div.style.overflow="hidden";
   if(div.style.display!="none")div.style.display="none";
   if(div.style.position!="absolute")div.style.position="absolute";
   
   if(isAnimated && aniSpeed>0)
   {xincr = parseInt(divWidth/aniSpeed);
    yincr = parseInt(divHeight/aniSpeed);
    animateToolTip = true;
    }
        
   isInit++; 
   
  }
  
    
  this.Show =  function(e,strHTML)
  {
    if(isInit<0) return;
    
    
    var newPosx,newPosy,height,width;
    if(typeof( document.documentElement.clientWidth ) == 'number' ){
    width = document.body.clientWidth;
    height = document.body.clientHeight;}
    else
    {
    width = parseInt(window.innerWidth);
    height = parseInt(window.innerHeight);
    
    }
    var curPosx = (e.x)?parseInt(e.x):parseInt(e.clientX);
    var curPosy = (e.y)?parseInt(e.y):parseInt(e.clientY);
    
    if(strHTML!=null)
    {html = strHTML;
     div.innerHTML=html;}
    
    if((curPosx+divWidth+10)< width)
    newPosx= curPosx+10;
    else
    newPosx = curPosx-divWidth;

    if((curPosy+divHeight)< height)
    newPosy= curPosy;
    else
    newPosy = curPosy-divHeight-10;

   if(window.pageYOffset)
   { newPosy= newPosy+ window.pageYOffset;
     newPosx = newPosx + window.pageXOffset;}
   else
   { newPosy= newPosy+ document.body.scrollTop;
     newPosx = newPosx + document.body.scrollLeft;}

    div.style.display='block';
    newPosy += BUMPDOWN;
    if (newPosy<BUMPDOWN) newPosy=BUMPDOWN;
    div.style.top= newPosy + "px";
    newPosx += BUMPRIGHT;
    if (newPosx<BUMPRIGHT) newPosx=BUMPRIGHT;
    div.style.left= newPosx + "px";

    div.focus();
    if(animateToolTip){
    div.style.height= "0px";
    div.style.width= "0px";
    ToolTipObject.animate(div.id,divHeight,divWidth);}
      
    
    }

    

   this.Hide= function(e)
    {div.style.display='none';
    if(!animateToolTip)return;
    div.style.height= "0px";
    div.style.width= "0px";}
    
   this.SetHTML = function(strHTML)
   {html = strHTML;
    div.innerHTML=html;} 
    
    ToolTipObject.animate = function(a,iHeight,iWidth)
  { a = document.getElementById(a);
         
   var i = parseInt(a.style.width)+xincr ;
   var j = parseInt(a.style.height)+yincr;  
   
   if(i <= iWidth)
   {a.style.width = i+"px";}
   else
   {a.style.width = iWidth+"px";}
   
   if(j <= iHeight)
   {a.style.height = j+"px";}
   else
   {a.style.height = iHeight+"px";}
   
   if(!((i > iWidth) && (j > iHeight)))      
   setTimeout( "ToolTipObject.animate('"+a.id+"',"+iHeight+","+iWidth+")",1);
    }
    
   Init(id);
}


function InsertToolTipAnchors() {
   var AnchorOut;
 
    AnchorOut="<div id=\"TT1\" style=\"";
    AnchorOut +="background-color:skyblue; ";
    AnchorOut +="width: 190px; ";
    AnchorOut +="height: 80px; ";
    AnchorOut +="border: solid 1px gray; ";
    AnchorOut +="text-align: center; ";
    AnchorOut +="font-weight: bold; ";
    AnchorOut +="filter: alpha(Opacity=100); opacity:1.00\">";
    AnchorOut +="&nbsp;</div>";

    AnchorOut +="<div id=\"TT2\" style=\"";
    AnchorOut +="background-color:white; ";
    AnchorOut +="width: 770px; ";
    AnchorOut +="height: 500px; ";
    AnchorOut +="border: solid 3px #151B54; ";
    AnchorOut +="text-align: center; ";
    AnchorOut +="font-weight: bold; ";
    AnchorOut +="filter: alpha(Opacity=100); opacity:1.00\"";
    AnchorOut +=">";
    AnchorOut +="&nbsp;</div>";

  document.getElementById("ToolTipAnchor").innerHTML=AnchorOut;
}


 ///////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////

   //

   function StartUp() {
       var strTemp;


           SessionID=CreateGUID();
           strTemp=GetParamFromThisURL("debug");
           
           if (strTemp!="") {
               IsDebugMode=true;
               document.getElementById("DebugModeState").innerHTML="<font color=\"RED\">Debug Mode ON </font><hr><br>";
           }

           CustomSessionID=GetParamFromThisURL("cc");
           if (CustomSessionID!="") {
               IsCustomSession=true;
               if (IsDebugMode) document.getElementById("CustomSessionID").innerHTML="<font color=\"RED\">Custom Session ID: </font>"+ CustomSessionID + "<br>";
           }

    
         //clear out the "Please Wait" message.
         document.getElementById("WaitMessage").innerHTML="<br>";
         
         if (IsDebugMode) {
             document.getElementById("MultiviewClientVersion").innerHTML="<font color=\"RED\">Client Version:</font> " +MULTIVIEWCLIENTVERSION + "<br>";
         }
         
         CookieIn=Trim(document.cookie);

       
         if (IsDebugMode) {
             document.getElementById("CookieIn").innerHTML="<font color=\"RED\">Cookie:</font> " + unescape(CookieIn) + "<br>";
         }
        
         if (!IsCustomSession && (CookieIn==null || CookieIn=="")) {
             alert ("No Session Configuration Found -- redirecting to Session Editor.");
             location.replace("SessionEditor.html");
             return;
         } else {
            if (!ParseCookies()) {
               alert ("No Valid Session Configuration Found -- redirecting to Session Editor.");
               location.replace("SessionEditor.html");
               return;
            }
         }


         document.getElementById("MainTable").innerHTML="<h3><img src=\"ajax-loader.gif\" height=\"32\" width=\"32\" style=\"float:left; border:0;\"><br>&nbsp;&nbsp;Requesting Bloodhound Data, Please Wait...</h3><br>";
  
         InsertToolTipAnchors();
         ToolTip1 = new ToolTipObject("TT1",true,0);
         ToolTip2 = new ToolTipObject("TT2",true,0); 
         if (IsDebugMode) {
             document.getElementById("SessionID").innerHTML= "<font color=\"RED\">Session ID:</font> " + SessionID + "<br>";
             document.getElementById("SessionTitle").innerHTML= "<font color=\"RED\">Session Title:</font> " + SessionTitle + "<br>";
         }

         if (InitDataRequest()) {
   		     LastAttemptInterval=0;
   		     LastAttemptIntervalID=setTimeout("UpdateTimeCounter()",TIMERINTERVAL);

   	     } else {
   		     return;
   	     }

   }
