
/* * * * * * * * * * * * * * * * * * * * * * *
 * EMC - Energy Meter Companion              *
 * http://www.techtrade.se/                  *
 * Copyright (c) 1998-2010 gk@techtrade.se   *
 * All rights reserved                       *
 *                                           *
 * EMC Web Server Ajax script                *
 * * * * * * * * * * * * * * * * * * * * * * *


*/


// ---------------------------------------------------------------
//
//   usage: addEvent(window, 'load', myInitFunction);
//
var addEventCounter = 0;
function addEvent(obj, evnt, func) {
  addEventCounter++;
  if(obj.addEventListener) {                      // Mozilla, Netscape, Firefox, Google Chrome
    obj.addEventListener(evnt, func, false);      // false = use event bubbling model, true = use event capturing model
  } else {                                        // IE
    obj.attachEvent('on' + evnt, func);
  }
}
//
// ---------------------------------------------------------------




var localStartTime = new Date();
var showServerTime = false;
var serverTime = null;
var emcTime = null;

var biGaugeClock=null;
var biGaugePower=null;

var graphUpdates=0;
var graphTimeOuts=0;
var imageURL = 'emcPlot.png';

var loadIMG = new Image();

var getGraphTimer = null;

var graphImgWidth = 200;
var graphImgHeight = 100;


var renderingMode = '';




var lastViewRangeIndex = -1;


var objLayoutDiv = null;
var objLayoutTable = null;
var objSplashScreen = null;


var objSelGraphTimeRange = null;

var objGraphImg = null;
var objPanelDivClock = null;
var objPanelDivPower = null;
var objPanelDivGraph = null;
var objPopupDivOptions = null;
var objPopupDivAjax = null;

var objGaugeDivClock = null;
var objGaugeDivPower = null;
var objGaugeDivTemp = null;

var gaugePower = null;        // emcPower -> gaugePower
var gaugeClock = null;        // clock    -> gaugeClock
var gaugeTemp = null;         // temp     -> gaugeTemp


var ajaxUpdates = 0;
var ajaxErrors = 0;
var ajaxTimeOuts = 0;

var lastClockSeconds = 0;

var clockInterval = 2000;
var ajaxInterval = 2000;
var minGraphInterval = 2000;
var graphUpdTimer = 0;
var lastGraphUpdData = 0;
var lastGraphGetURL = '';
var lastGraphStrTime = '';
var graphTrackMeter = true;

var ajaxRequestTime = new Date();
var ajaxEndTime = new Date();
var ajaxResponseTime = new Date();

var showRelativePower = false;
var relativeRefPower = 0;
var lastPowerValue = -1;

var sumOfPowerValues = 0;
var countOfPowerValues = 0;
var averagePower = 0;


var xhrReadyState = 4;


var whAvgStartValue = null;
var whAvgStartTime = null;


function strRight(s, n) {
   var e = s.length;                //Declare variables.
   var r = s.substring(e - n, e);   //Declare variables.
   return(r);                       //Return date.
}

function fmtDateTime(d) {
   var s = '';                         //Declare variables.

   s += strRight('000' + d.getFullYear(), 4) + '-';
   s += strRight('0' + (d.getMonth() + 1), 2) + '-';
   s += strRight('000' + d.getDate(), 2) + ' ';

   s += strRight('0' + d.getHours(), 2) + ':';
   s += strRight('0' + d.getMinutes(), 2) + ':';
   s += strRight('0' + d.getSeconds(), 2) + ':';
   s += strRight('00' + d.getMilliseconds(), 3);

   return(s);       //Return dateTime.
}



function parseDateTime(strDate) {
// 0123456789012345678
// 2008-10-19 15:51:40

/*

  any none digit char can be used as delimiter

  2008-10-19 15:51:40.123
  2008-10-19 15:51
  2008-10-19 15
  2008-10-19
  2008-10
  2008

*/


  var s = strDate.replace(/[^0-9]+/g, ',')  // substitute ',' for all sequences of none digits
  s = s.replace(/\,$/, '')                  // remove trailing delimiter
  s = s.replace(/^\,/, '')                  // remove leading delimiter

  var d = new Date();

  var y = d.getFullYear();
  var m = d.getMonth();
  var c = d.getDate();

  var h = d.getHours();
  var n = d.getMinutes();
  var t = d.getSeconds();
  var u = d.getMilliseconds();

//  window.status = 'x' + s + 'x' + ' s.length=' + s.length + ' y=' + y;

  if (s.length > 0) {

    var a = s.split(",");
    var i = a.length;
  
    u = (i >= 7) ? parseInt(a[6], 10) : 0;
    t = (i >= 6) ? parseInt(a[5], 10) : 0;
    n = (i >= 5) ? parseInt(a[4], 10) : 0;
    h = (i >= 4) ? parseInt(a[3], 10) : 0;
    c = (i >= 3) ? parseInt(a[2], 10) : 1;
    m = (i >= 2) ? parseInt(a[1], 10) - 1 : 0;
    y = (i >= 1) ? parseInt(a[0], 10) : 0;
  
    if (y < 100) {
       y += 2000;
    }
  
    d.setFullYear(y, m, c);
    d.setHours(h, n, t, u);

//  window.status = 'x' + s + 'x' + ' s.length=' + s.length  + ' a.length=' + i + ' y=' + y + ' d=' + d;

  }
  
//  window.status = 'y=\'' + y + '\' m=\'' + m + '\' d=\'' + c + '\'  h=\'' + h + '\' n=\'' + n + '\' s=\'' + t + '\'   dLen=' + dLen + '   tStart=' + tStart + '   tLen=' + tLen;

  return d;
}





function setPowerLabelValue() {
  var numPower = lastPowerValue;

  if (numPower >= 0) {

    if (showRelativePower) {
      numPower -= relativeRefPower;
      if (numPower < 0) {
  		  gaugePower.labelW.setText(' ' + numPower.toString() + ' ');
      } else if (numPower == 0) {
  		  gaugePower.labelW.setText(' ' + numPower.toString() + ' ');
      } else {
  		  gaugePower.labelW.setText(' +' + numPower.toString() + ' ');
      }

    } else {
		  gaugePower.labelW.setText(' ' + numPower.toString() + ' ');
    }
  
  } else {

		gaugePower.labelW.setText(' E' + numPower.toString() + ' ');
  }
}


function setAveragePowerNeedle() {
  var numPower = lastPowerValue;
  if (numPower >= 0) {
    /* calculate average power from received power value */
    sumOfPowerValues += numPower;
    countOfPowerValues ++;
    averagePower = sumOfPowerValues / countOfPowerValues;
  	gaugePower.needle2.setStyleProperty('display','');
  	gaugePower.needle2.setValue(averagePower);
  } else {
  	gaugePower.needle2.setStyleProperty('display','none');
  }
}


// -------------------------------------------
// -------------------------------------------
// -------------------------------------------



// -------------------------------------------
// -------------------------------------------
// -------------------------------------------
    

  
function xhrReadystateChanged() {

  xhrReadyState = xhr.readyState;
  
  document.ajax.ajaxReadyState.value = xhrReadyState;

  if(xhrReadyState == 4) {

    ajaxEndTime = new Date();
    ajaxResponseTime = ajaxEndTime - ajaxRequestTime;
    document.ajax.ajaxResponseTime.value = ajaxResponseTime;


    document.ajax.ajaxStatus.value = xhr.status;
    if(xhr.status  == 200) {
//      document.ajax.dyn="Received:"  + xhr.responseText; 
      ajaxUpdates++;
      document.ajax.ajaxUpdates.value = ajaxUpdates;

      var xServer = xhr.getResponseHeader('Server');
      document.ajax.ajaxServerName.value = xServer;

      serverTime = new Date(xhr.getResponseHeader('Date'));
/*
      document.ajax.ajaxTimeOuts.value = xhr.getResponseHeader('Date');
      document.ajax.ajaxErrors.value = fmtDateTime(serverTime);
*/

      if (showServerTime) {
        showTime(serverTime);
      }


      if (gaugePower != null) {

// emcTime emcEnergy emcPower
        var xdoc = xhr.responseXML;   // Assign the XML file to a var

        var emcDataElement = xdoc.getElementsByTagName('emcData')[0];              // Read the emcData (root) element

        if (emcDataElement == null) {
          window.status='emcDataElement == null';
          return false;
        }
        
        var emcRecordElements = xdoc.getElementsByTagName('emcRecord');            // get all emcRecords element

        if (emcRecordElements.length < 1) {
          window.status='emcRecordElements.length = ' + emcRecordElements.length;
          return false;
        }

        var emcRecordElement = emcRecordElements[0];                               // Read the first emcRecord element

        if (emcRecordElements != null) {
//        if (emcRecordElement != null) {

//2008-10-11 14:53:59 0000000562 00004390
//timeStamp of last pulse, Wh after last pulse, power (W) between 2 last pulses


        if (!emcRecordElement.hasChildNodes()) {
          window.status='emcRecordElement.hasChildNodes() = false';
          return false;
        }

//           1         2         3         4         5         6
// 012345678901234567890123456789012345678901234567890123456789012345678901234567890
// 2010-04-12 17:29:15 0124000300 00000475
// 2010-04-12 17:29:15 0124000300 00000475 123 123 123
// 2010-04-12 18:11:31 0124000632 00000472 000006 000155 000006 000006
// 2010-04-12 18:10:45 0124000626 00000471 -00006 -00156 -00006 -00006
//                                         temp   volt   status resetCnt
// 2010-04-12 18:42:03 0124001018 00015280 -32767 -32768 000000 000001     No EMC-Controller
//
//          var strEmcRecord = emcRecordElement.firstChild.data.toString();
          var strEmcRecord = emcRecordElement.firstChild.data;
          if (strEmcRecord.length != 39 && strEmcRecord.length != 67) {
            var strTime = 'error data length=' + strEmcRecord.length;

          } else {

            var strTime = strEmcRecord.substr(0, 19);
            var strEnergy = strEmcRecord.substr(20, 10);
            var strPower = strEmcRecord.substr(31, 8);
            var strTemp = '';
            var tempC = -128;

            if (strEmcRecord.length == 67) {
              strTemp = strEmcRecord.substr(40, 6);
              tempC = parseFloat(strTemp);
              if (tempC >= -256 && tempC <= 256) {
  //            var tempC = ((tempCnt + 256 * (tempCnt > 127)) + 40) / 2#
                if (tempC > 127)
                  tempC -= 256;
                tempC += 40;
                tempC /= 2;
                strTemp += ' (' + tempC +')'
              } else {
                tempC = -128;
              }
            }

            emcTime = parseDateTime(strTime);

            document.ajax.emcTime.value= strTime;           // show in ajax status
            document.ajax.emcEnergy.value = strEnergy;      // show in ajax status
            document.ajax.emcPower.value = strPower;        // show in ajax status
            document.ajax.emcTemp.value = strTemp;          // show in ajax status

            if (gaugeTemp != null) {
              setGaugesTempScale();
              if (tempC == -128) {
              	gaugeTemp.needle1.setStyleProperty('display','none');
                if (gaugeTemp.labelC) {
                  gaugeTemp.labelC.setText('OFF');
                }
              } else {
              	gaugeTemp.needle1.setStyleProperty('display','');
                gaugeTemp.needle1.setValue(tempC);
                if (gaugeTemp.labelC) {
                  gaugeTemp.labelC.setText(tempC.toFixed(1));
                }
              }
            }
    
            var numEnergy = parseInt(strEnergy, 10);
            var numPower = parseInt(strPower, 10);

            lastPowerValue = numPower;
  
            if (numPower < 0) {
            	gaugePower.needle.setStyleProperty('display','none');

              whAvgStartValue = null;
              whAvgStartTime = null;

            } else { // (numPower >= 0)
    
              if (numEnergy < 0) {
            		gaugePower.labelkWh.setText('ERROR');

              } else { // (numEnergy >= 0)

                var numEnergykWh = numEnergy/1000;
            		gaugePower.labelkWh.setText(numEnergykWh.toFixed(3));


              } // (numEnergy >= 0)
  
            	gaugePower.needle.setStyleProperty('display','');
           		gaugePower.needle.setValue(numPower);
            
            } // (numPower >= 0)

            setAveragePowerNeedle();
            setPowerLabelValue();

            if (gaugeClock != null) {
              gaugeClock.needlePowerUpd.setValue(lastClockSeconds);
            }


            if (graphTrackMeter) {
              if (strEmcRecord != lastGraphUpdData) { // new pulse record received

                if (graphUpdTimer >= minGraphInterval) {
                  setGraphEndTimeValue(strTime);
                  lastGraphUpdData = strEmcRecord;

                }
              }
            }

          } // (strEmcRecord.length == 39)

        } /* emcRecordElements != null */

      } /* gaugePower != null */
      
    } else {
      ajaxErrors++;
      document.ajax.ajaxErrors.value = ajaxErrors;
    }

  }  // xhrReadyState == 4

} 





function reloadWindow() {
    window.location = window.location;
}


var reloadTimer = null;

var oldWindowWidth=0;   //document.body.offsetWidth;
var oldWindowHeight=0;  //document.body.offsetHeight;
var resizeCount=0;      //document.body.offsetHeight;
var resizeChanged=0;    //document.body.offsetHeight;

function windowResize() {
  var newWindowWidth=document.body.offsetWidth;
  var newWindowHeight=document.body.offsetHeight;
  resizeCount++;
  if (newWindowWidth != oldWindowWidth || newWindowHeight != oldWindowHeight) {
    if (true) {
      resizeChanged++;
//    window.status='windowResize: total=' + resizeCount + ' changed=' + resizeChanged + ' w1=' + oldWindowWidth + '  h1=' +oldWindowHeight + ' w2=' + newWindowWidth + '  h2=' +newWindowHeight;
      oldWindowWidth=newWindowWidth;
      oldWindowHeight=newWindowHeight;

      if (getGraphTimer != null) {
        clearTimeout(getGraphTimer);
      }
      getGraphTimer = null;

  		if (updTimer != null)
  		  clearTimeout(updTimer);

    	if (reloadTimer != null)
    	  clearTimeout(reloadTimer);

      reloadTimer = setTimeout(reloadWindow, 5000);
    }
  }
}



/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */

var scrollRNGen=true;
var scrollRNGenCnt=0;

function scrollRage(scrollDir) {
  var rngScrollObj = document.getElementById('rngScroll');

//  scrollRNGenCnt++;

//  window.status='scrollRNGenCnt = ' + scrollRNGenCnt + '  rngScrollObj.scrollLeft = ' + rngScrollObj.scrollLeft + '  scrollDir=' + scrollDir + '  scrollRNGen=' + scrollRNGen;

  if (scrollRNGen == true) {
    scrollRNGen = false;

    if (scrollDir != 1) {                      /* not reset */

      scrollRNGenCnt++;

      if (objSelGraphTimeRange != null) {
    
        selectedViewRangeIndex = objSelGraphTimeRange.selectedIndex;
    
        var colSelOpt = objSelGraphTimeRange.getElementsByTagName('OPTION');
        var lastViewRangeIndex = colSelOpt.length - 1;
    
    
//       window.status = '  lastViewRangeIndex=' + lastViewRangeIndex + '  scrollDir=' + scrollDir + '  scrollWidth=' + rngScrollObj.scrollWidth + '  offsetWidth=' + rngScrollObj.offsetWidth + '  objSelGraphTimeRange.selectedIndex=' + objSelGraphTimeRange.selectedIndex + '  rnd=' + Math.random();
        if (scrollDir == 0) {
          if (selectedViewRangeIndex > 0) {
            selectedViewRangeIndex--;
          }
        } else {
          if (selectedViewRangeIndex < lastViewRangeIndex) {
            selectedViewRangeIndex++;
          }
        }
        objSelGraphTimeRange.selectedIndex = selectedViewRangeIndex;
  
        setGetGraphTimer();
    
      }

    }

    setTimeout("scrollRNGen=true", 200);      // grrr IE8

  }

  rngScrollObj.scrollLeft = 1;

}

var scrollGETen=true;
var scrollGETenCnt=0;


function scrollGraphEndTime(scrollDir) {

  var endScrollObj = document.getElementById('endScroll');

//  window.status='scrollGETenCnt = ' + scrollGETenCnt + '  endScrollObj.scrollLeft = ' + endScrollObj.scrollLeft + '  scrollDir=' + scrollDir;

  if (scrollGETen == true) {
    scrollGETen = false;

    if (scrollDir < 1 || scrollDir > 1 ) {    /* logical OR */

//  window.status='scrollGETenCnt = ' + scrollGETenCnt + '  endScrollObj.scrollLeft = ' + endScrollObj.scrollLeft + '  scrollDir=' + scrollDir + '  ****';

      var chkEndObj = document.getElementById('chkNow');
      if (chkEndObj != null) {
        if (chkEndObj.checked == true) {
          chkEndObj.checked = false;
          toggleSelEndTime(false);
        }
      }
    
      var inpEndObj = document.getElementById('inpEndTime');
      if (inpEndObj != null) {
    
        var d = parseDateTime(inpEndObj.value);   /* convert to Date */

        if (isNaN(d)) {
          inpEndObj.style.color='red';
        } else {
      
          var graphViewTimeMs = 0;
          var graphViewTimeMonth = 0;
    
          var graphViewTimeHours = 0;
          var graphViewTimeMinutes = 0;
          var graphViewTimeSeconds = 0;
    
          var graphViewStep = selectedViewRangeIndex + 1;
    
          var sDir = (scrollDir == 0) ? -1 : 1;
    
          /* 0   1     2       3       4      5     6   7   8  9  10 11  12  13 14  */
          /* all 1year 6months 3months 1month 1week 24h 12h 6h 3h 1h 30m 15m 5m 1min */
      
                                              /* 0     1   2   3  4  5  6   7   8  9    */
    
          if (graphViewStep == 15) {  /* 15sec */
            graphViewTimeSeconds = sDir * 15;
    
          } else if (graphViewStep >= 11) {  /* 30m 15m 5m 1min */
            graphViewTimeMinutes = sDir * Array(30, 15, 5, 1)[graphViewStep - 11];
    
          } else if (graphViewStep >= 5) {  /* 1week  24h 12h 6h 3h 1h 30m */
            graphViewTimeHours =    sDir * Array(7 * 24, 24, 12, 6, 3, 1, 0.5)[graphViewStep - 5];
    
          } else {                    /* all 1year 6months 3months 1month */
            graphViewTimeMonth = sDir * Array(0, 12, 6, 3, 1)[graphViewStep];
    
          }
  
          var newEndTime = new Date(d.getFullYear(), 
                                    d.getMonth() + graphViewTimeMonth,
                                    d.getDate(),
                                    d.getHours() + graphViewTimeHours,
                                    d.getMinutes() + graphViewTimeMinutes,
                                    d.getSeconds() + graphViewTimeSeconds);
  
          setGraphEndTimeValue(fmtDateTime(newEndTime).substr(0,19));
  
        }
    
      }   // inpEndObj != null

      scrollGETenCnt++;
  
    } // scrollDir != 1

      setTimeout("scrollGETen=true", 200);      // grrr IE8

  } // scrollGETen == true

      endScrollObj.scrollLeft = 1;
  
}



function graphRangeChanged(selIndex) {
  selectedViewRangeIndex = selIndex;
  setGetGraphTimer();
}


function setGraphEndTimeValue(newValue) {
  var inpEndObj = document.getElementById('inpEndTime');
  if (inpEndObj != null) {
    inpEndObj.value = newValue;
    checkGraphEndTimeValueChanged('set');
  }
}

var lastGraphEndTimeValue = '';
var checkGraphEndTimeValueChangedCount = 0;

function checkGraphEndTimeValueChanged(dMsg) {
  checkGraphEndTimeValueChangedCount++;
  var inpEndObj = document.getElementById('inpEndTime');
  if (inpEndObj != null) {
    var graphEndTimeValue = inpEndObj.value;
    if (graphEndTimeValue != lastGraphEndTimeValue) {
      lastGraphEndTimeValue = graphEndTimeValue;
      inpEndObj.style.color='blue';
      var btnGraphObj = document.getElementById('btnGraph');
      if (btnGraphObj != null) {
//        btnGraphObj.style.display = '';
      }
      setGetGraphTimer();
    }
//    window.status= 'new value =' + graphEndTimeValue +  '  count =' + checkGraphEndTimeValueChangedCount +  '  dMsg=' + dMsg;
  }
}


var pendingGraphRequests = 0;
var peakPendingGraphRequests = 0;
var totalGraphRequests = 0;

function setGetGraphTimer() {
  if (getGraphTimer == null) {
    getGraphTimer = setTimeout(stopGetGraphTimer, 1000);
    pendingGraphRequests = 0;
    getUserGraph();
  } else {
    pendingGraphRequests++;
    if (pendingGraphRequests > peakPendingGraphRequests) {
      peakPendingGraphRequests = pendingGraphRequests;
    }
  }

  if (!graphTrackMeter) {

    var btnGraphObj = document.getElementById('btnGraph');
    if (btnGraphObj != null) {
//      btnGraphObj.style.display = '';
    }
  } else {
    peakPendingGraphRequests = 0;
  }

}

function stopGetGraphTimer() {
  if (getGraphTimer != null) {
    clearTimeout(getGraphTimer);
  }
  getGraphTimer = null;
  if (pendingGraphRequests != 0) {
    pendingGraphRequests = 0;
//    window.status = '  pendingGraphRequests1=' + pendingGraphRequests + '  peak=(' + peakPendingGraphRequests +')';
    getUserGraph();
  }

}


function getUserGraph() {

    totalGraphRequests++;

//    window.status = '  pendingGraphRequests1=' + pendingGraphRequests + '  peak=(' + peakPendingGraphRequests +')' + '  total=' + totalGraphRequests;
    
    var inpEndObj = document.getElementById('inpEndTime');
    if (inpEndObj != null) {
  
//      window.status = '  selectedViewRangeIndex=' + selectedViewRangeIndex + '  graphViewTimeMs=' + graphViewTimeMs;

      var strGraphEndTime = inpEndObj.value;               /* convert to Date */

/*
      if (graphTrackMeter) {
        strGraphEndTime = lastGraphStrTime;
      }
*/      
      var d = parseDateTime(inpEndObj.value);   /* convert to Date */


//    if (!(1998 <= d.getFullYear() && d.getFullYear() <= 2098)) {
      if (isNaN(d)) {
        inpEndObj.style.color='red';
      } else {
        if (true || graphUpdTimer >= minGraphInterval) {

          if (objGraphImg.src != loadIMG.src) {
            graphTimeOuts++;
            document.ajax.graphTimeOuts.value = graphTimeOuts;
          }

          var graphGetURL = imageURL;
          var graphGetPar = '';


          if (document.graphOptions.w.value.length > 0)
            graphGetPar += '&w=' + encodeURIComponent(document.graphOptions.w.value);
          else
            graphGetPar += '&w=' + graphImgWidth;

          if (document.graphOptions.h.value.length > 0)
            graphGetPar += '&h=' + encodeURIComponent(document.graphOptions.h.value);
          else
            graphGetPar += '&h=' + graphImgHeight;

          graphGetPar += '&c=' + encodeURIComponent(document.graphOptions.c.value);


//http://fnatte:60374/emcPlot.gif?d=1&w=460&h=268&b=FFFF7f&c=ffffff&m=0&o=0&p=&t=&r=13&e=
          graphGetPar += '&d=1';
//          graphGetPar += '&w=400';
//          graphGetPar += '&h=200';
//        graphGetPar += '&b=FFd0d0';
//        graphGetPar += '&b=A6CAF0';   /* sparel blue */
//        graphGetPar += '&b=00FFFF';   /* yellow */
//        graphGetPar += '&b=0000FF';   /* red */

//        graphGetPar += '&b=F0CAA6';   /* sparel blue (bbggrr) VB-color=&HBBGGRR& */

          if (document.graphOptions.b.value.length == 0) {
            if (objPanelDivGraph) {
  //          graphGetPar += '&b=' + vbColor('' + getStyle(objPanelDivGraph, 'backgroundColor'));  // returns rgb() in FF
              graphGetPar += '&b=' + encodeURIComponent('' + getStyle(objPanelDivGraph, 'backgroundColor'));  // returns rgb() in FF
  //            window.status=graphGetPar;
            } //encodeURI(URIString) encodeURIComponent
          } else {
            graphGetPar += '&b=' + encodeURIComponent(document.graphOptions.b.value);
          }

          graphGetPar += '&p=' + document.graphOptions.p.value;
          graphGetPar += '&t=' + document.graphOptions.t.value;
//        graphGetPar += '&o=' + (document.graphOptions.o.checked ? 1 : 0);
//        graphGetPar += '&q=' + (document.graphOptions.q.checked ? 1 : 0);

          graphGetPar += addCheckedValue(document.graphOptions.o);
          graphGetPar += addCheckedValue(document.graphOptions.q);

          graphGetPar += addTextValue(document.graphOptions.v);



//        graphGetPar += '&o=' + getCheckedValue(document.graphOptions.o, 'o');
                                 
          
          graphGetPar += '&m=' + (document.graphOptions.m.checked ? 1 : 0);



          var xGridSteps = 8;

                          /* 0    1   2   3   4   5   6   7   8   9  10  11  12  13  14  */
                          /* all 1y  6m  3m  1m  1w  24h 12h  6h  3h 1h 30m 15m  5m  1m  */
          xGridSteps = Array(0,  12,  6,  3,  4,  7,  8, 12,  6,  3, 12,  6,  3,  5, 12)[selectedViewRangeIndex];

          graphGetPar += '&g=' + xGridSteps + ',8';

          graphGetPar += '&r=' + objSelGraphTimeRange.value;

          var strGraphTime = fmtDateTime(d)
          var eGraphTime = strGraphTime.substr(0, 10) + 'T' + strGraphTime.substr(11, 8);
          document.ajax.eGraphTime.value = eGraphTime;

          graphGetPar += '&e=' + eGraphTime;

          if (graphGetPar.length){
            graphGetURL += '?' + graphGetPar.substr(1);
          }

          loadIMG.src = graphGetURL;
          graphUpdTimer = 0;
  
          lastGraphGetURL = graphGetURL;
          lastGraphStrTime = strGraphEndTime;
  
        } else {
//          window.status = 'getUserGraph: no update';
        }

      }

  
    }

}

// from textbox 
function addTextValue(objTextBox) {
  if (objTextBox.value.length > 0)
    return '&' + objTextBox.name + '=' + encodeURIComponent(objTextBox.value);
  return '';
}

// from checkbox 
function addCheckedValue(objCheckBox) {
  if (objCheckBox.checked)
    return '&' + objCheckBox.name + '=' + objCheckBox.value;
  return '';
}

// from radio 
function getSelectedValue(collObj, sName) {
// var collObj = document.getElementsByName(sName); 
  for (var i=0;i<collObj.length;i++) {
    if (collObj[i].checked)
      return collObj[i].value;
  }
  return '';
}

function getStyle(el, cssprop) {
  if (el.currentStyle)                  //IE
    return el.currentStyle[cssprop]
  else if (document.defaultView && document.defaultView.getComputedStyle) //Firefox
    return document.defaultView.getComputedStyle(el, "")[cssprop]
  else //try and get inline style
    return el.style[cssprop]
}


// #A6CAF0 -> F0CAA6
function vbColor(c) {
  var bbggrr = c;
  if (c.indexOf('#') == 0) {
    // Handle the #BBGGRR format
    if (c.length == 7) {
      bbggrr = c.substr(5, 2) + c.substr(3, 2) + c.substr(1, 2);
    }
  } else if (c.indexOf('r') == 0) {
    // Handle rgb(r, g, b) format
    // get rid off "rgb(" and ")"
    var d = c.substring(c.indexOf('(') + 1, c.indexOf(')'));
    var rgbColors = d.split(',', 3);

    // Convert r g b to hex2 strings
    rgbColors[0] = strRight('0' + (parseInt(rgbColors[0]).toString(16)), 2);
    rgbColors[1] = strRight('0' + (parseInt(rgbColors[1]).toString(16)), 2);
    rgbColors[2] = strRight('0' + (parseInt(rgbColors[2]).toString(16)), 2);
    bbggrr = rgbColors[2] + rgbColors[1] + rgbColors[0];

  }

//  window.status = 'vbColor: c=' + c + '  bbggrr=' + bbggrr;

  return bbggrr;    // vbColor = &HBBGGRR&
}




function newGraphLoaded() {
  graphUpdates++;
  document.ajax.graphUpdates.value = graphUpdates;

  if (getGraphTimer != null) {
//    clearTimeout(getGraphTimer);
  }

  if (objGraphImg.src != loadIMG.src) {
    objGraphImg.src = loadIMG.src;
    if (gaugeClock != null) {
//		gaugeClock.needleGraphUpd.setVisible(true);
      gaugeClock.needleGraphUpd.setValue(lastClockSeconds);
    }
  }

//  if (!graphTrackMeter) {
  if (true) {
    var btnGraphObj = document.getElementById('btnGraph');
    if (btnGraphObj != null) {
      btnGraphObj.style.display = 'none';
    }

    var inpEndObj = document.getElementById('inpEndTime');
    if (inpEndObj != null) {
      inpEndObj.style.color='black';
    }
  }

}



/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */

var graphToolsVisible=false;

function toggleGraphTools() {
  graphCtrlObj = document.getElementById('graphCtrl');
  if (graphCtrlObj != null) {
    graphToolsVisible =! graphToolsVisible;
    graphCtrlObj.style.display = (graphToolsVisible) ? '' : 'none';
  }

  if (graphToolsVisible) {
    var rngScrollObj = document.getElementById('rngScroll');
    if (rngScrollObj != null) {
      rngScrollObj.scrollLeft = 1;
    }
  
    var endScrollObj = document.getElementById('endScroll');
    if (endScrollObj != null) {
      endScrollObj.scrollLeft = 1;
    }
    scrollRage(1); /* set current selected range index */
  }
}


function toggleSelEndTime(nowFlag) {
    graphTrackMeter = nowFlag;

    var inpEndObj = document.getElementById('inpEndTime');
    if (inpEndObj != null) {
      inpEndObj.style.backgroundColor = (nowFlag) ? '#D0D0D0' : 'white';
    }

    if (graphToolsVisible) {
      var rngScrollObj = document.getElementById('rngScroll');
      if (rngScrollObj != null) {
        rngScrollObj.scrollLeft = 1;
      }
    
      var endScrollObj = document.getElementById('endScroll');
      if (endScrollObj != null) {
        endScrollObj.scrollLeft = 1;
      }
      scrollRage(1); /* set current selected range index */
    }
}


function toggleGraphOptions(onFlg) {
  if (objPopupDivOptions != null) {
    objPopupDivOptions.style.display = (onFlg == true) ? '' : 'none';
  }
  if (onFlg == false) {
    toggleAjaxStatus(onFlg);
  } else {
    var chkShowAjaxStatusObj = document.getElementById('chkShowAjaxStatus');
    if (chkShowAjaxStatusObj != null) {
      if (chkShowAjaxStatusObj.checked) {
        toggleAjaxStatus(onFlg);
      } 
    } 
  } 
}

function toggleServerTime(onFlg) {
  showServerTime = onFlg;
  var text = (onFlg == true) ? 'Server Time' : 'Local Time';
  var text = (onFlg == true) ? 'Server Time' : '';

	if (gaugeClock != null) {
    if (gaugeClock.meterTitle) {
      gaugeClock.meterTitle.setText(text);
    }
   	gaugeClock.needleHours.setStyleProperty('display','none');
   	gaugeClock.needleMinutes.setStyleProperty('display','none');
   	gaugeClock.needleSeconds.setStyleProperty('display','none');
  }
}

function toggleAdvancedOptions(onFlg) {
  var objAdvancedOptions = document.getElementById('advancedOptions');
  if (objAdvancedOptions) {
    objAdvancedOptions.style.display = (onFlg == true) ? '' : 'none';
  }
}


function toggleAjaxStatus(onFlg) {
  if (objPopupDivAjax != null) {
    objPopupDivAjax.style.display = (onFlg == true) ? '' : 'none';
  }
}


function toggleRelativePower(onFlg) {
  showRelativePower = onFlg;
//	gaugePower.needle3.setVisible(showRelativePower);
  if (showRelativePower) {
  	gaugePower.needle3.setStyleProperty('display','');
    relativeRefPower = lastPowerValue;
 		gaugePower.needle3.setValue(relativeRefPower);
    sumOfPowerValues = 0;
    countOfPowerValues = 0;
    setAveragePowerNeedle();
  } else {
  	gaugePower.needle3.setValue(0);
  	gaugePower.needle3.setStyleProperty('display','none');
  }

  setPowerLabelValue();
}


/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */


function getXHR() {
  var newReq = null;
	if(window.XMLHttpRequest) {
    try {
      newReq = new XMLHttpRequest();
    }
    catch(e) {
      newReq = false;
    }
  } else if(window.ActiveXObject) {
    try {
      newReq = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch(e) {
      try {
        newReq = new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch(e) {
        newReq = false;
      }
    }
  }
  return newReq;
}

var xhr = null;
// xhr = getXHR();

function loadXHR(url) {
  if (xhr != null) {
    xhr.open('GET', url, true);
    xhr.onreadystatechange = xhrReadystateChanged;
    xhr.send();
  } else {
//  alert('loadXHR(): XMLHttpRequest is not available');
  }
}


function getEmcXmlData() {
  var ajaxGetUrl = document.ajax.ajaxGetUrl.value;
  if (ajaxGetUrl.length > 0) {
    var ajaxGetURI = ajaxGetUrl;
    ajaxRequestTime = new Date();
    document.ajax.ajaxRequestTime.value = fmtDateTime(ajaxRequestTime);
    document.ajax.ajaxStatus.value = 'waiting';
    loadXHR(ajaxGetURI);
  }
} /* getEmcXmlData */


function showTime(x) {
	var t = { h: x.getHours(), m: x.getMinutes(), s: x.getSeconds() };
	if (gaugeClock != null) {

   	gaugeClock.needleHours.setStyleProperty('display','');
   	gaugeClock.needleMinutes.setStyleProperty('display','');
   	gaugeClock.needleSeconds.setStyleProperty('display','');

		gaugeClock.needleHours.setValue(t.h % 12 + t.m/60);
		gaugeClock.needleMinutes.setValue(t.m + t.s/60);
		gaugeClock.needleSeconds.setValue(t.s);
  }
}

// dynamically update the gauges at runtime
function updateClock() {
	var localTime = new Date();
  var sec = localTime.getSeconds();
  
  if (sec != lastClockSeconds) {
    var newSeconds = sec - lastClockSeconds;
    lastClockSeconds = sec;

    if (!showServerTime) {
      showTime(localTime);
    }

    if (sec % ajaxInterval == 0) {
      if (xhrReadyState != 4) {
        ajaxTimeOuts++;
        document.ajax.ajaxTimeOuts.value = ajaxTimeOuts;
      }
      getEmcXmlData();
    }
    graphUpdTimer++;
  }
}


function setTimers() {
  clockInterval = document.ajax.clockInterval.value.valueOf();
	if (clockInterval < 1000){
	  document.ajax.clockInterval.style.color='red';
		if (updTimer != null)
		  clearTimeout(updTimer);

  } else {
	  document.ajax.clockInterval.style.color='blue';
    updTimer = setInterval(updateClock, clockInterval);
  }

  ajaxInterval = document.ajax.ajaxInterval.value.valueOf();
  minGraphInterval = document.ajax.minGraphInterval.value.valueOf();

}


/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */


function ttlinkMouseOver(e) {
  var e=window.event.srcElement;
	e.style.color="#FFFFFF";
//  	alert('hej');
}


function ttlinkMouseOut() {
  var e=window.event.srcElement;
	e.style.color="#555555";
}

function ttlinkClicked() {
    window.location = ttLinkUrl;
}


var updTimer = null;
var ttLinkObj  = null;
var ttLinkUrl  = '';


var gaugeTempScaleIsSet = false;

function setGaugesTempScale() {
  if (!gaugeTempScaleIsSet) {
    gaugeTempScaleIsSet = true;
	  if (gaugeTemp.meterTitle) {
	     gaugeTemp.meterTitle.setText('Temp °C');    //Temp C°  xxxx "    "
    }
  }
}


/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */

// Load the gauges

function loadGauges() {
  var tempWidth=0;
  var clockWidth=0;
  var clockDivWidth=0;
  var pLeft1=0;
  var pRight1=0;
  var pLeft=0;
  var pRight=0;
  var clockDivWidthP=0;
  var clockDivHeight=0;


  if (objGaugeDivClock != null); {
    if (tempWidth != 0) {
      clockWidth = clockDivWidth-tempWidth;
      objGaugeDivClock.style.width=clockWidth + 'px';
    } else {
//  objGaugeDivClock.style.width = objPanelDivClock.style.width;
    }
//  objGaugeDivClock.style.height = objPanelDivClock.style.height;
      gaugeClock = bindows.loadGaugeIntoDiv(usePrefix + 'gauge_clock_03.xml', 'gaugeDivClock');

//  	  gaugeClock.meterTitle.setText('Server Time');

	}

  if (objGaugeDivTemp != null) {
		gaugeTemp = bindows.loadGaugeIntoDiv(usePrefix + 'gauge_temp_03.xml', 'gaugeDivTemp');
	}

	
  if (objGaugeDivPower != null); {
		gaugePower = bindows.loadGaugeIntoDiv(usePrefix + 'gauge_power_03.xml', 'gaugeDivPower');
   	gaugePower.needle.setStyleProperty('display','none');
   	gaugePower.needle2.setStyleProperty('display','none');
   	gaugePower.needle3.setStyleProperty('display','none');

 		gaugePower.labelkWh.setText(' no data ');
		gaugePower.labelW.setText(' no data ');

		gaugePower.scaleLabels.setEndValue(pwrFullScale);
		gaugePower.scaleLabels.setLabelCount(9);
		gaugePower.ticksMinor.setTickCount(41);
		gaugePower.ticksMajor.setTickCount(9);
		 
		gaugePower.scaleSection.setEndValue(pwrFullScale);

	  gaugePower.meterTitle.setText('Fårhagsv 19');
//  gaugePower.ttLink.setText(' Powered by TechTrade ');
	  gaugePower.ttLink.setText('Relative');

    ttLinkUrl = 'http://www.techtrade.se/sv/pwrmeter.asp';
    ttLinkObj = document.getElementById('ttlink');    // works only in IE (VML), returns null in firefox
    ttLinkObj = null;
    if (ttLinkObj != null) {
      ttLinkObj.style.cursor='hand';
      addEvent(ttLinkObj, 'mouseover', ttlinkMouseOver);
      addEvent(ttLinkObj, 'mouseout', ttlinkMouseOut);
      addEvent(ttLinkObj, 'click', ttlinkClicked);


    } else {
//      alert('no ttlink');
//      window.status='no ttlink';
    }

	}

}


/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */



function resizeGauges() {

//  var bcw = document.body.clientWidth;
//  var bch = document.body.clientHeight;

  if (objLayoutDiv) {
    var bcw = objLayoutDiv.clientWidth;
    var bch = objLayoutDiv.clientHeight;
  } else {
    var bcw = document.body.clientWidth;
    var bch = document.body.clientHeight;
  }
  
  var gcw = objPanelDivGraph.clientWidth;
  var gch = objPanelDivGraph.clientHeight;
  var gow = objPanelDivGraph.offsetWidth;
  var goh = objPanelDivGraph.offsetHeight;

  graphImgWidth = gcw;
  graphImgHeight = gch;

  var hbw = gow - gcw;  // horizontal border widths
  var vbw = goh - gch;  // vertical border widths

  bch = Math.max(goh + 100, bch);  // set minimum height
  bcw = Math.max(gow + goh + 100, bcw);  // set minimum height

  if (objPanelDivPower) {
    var pdpW = (bcw - gow - hbw);
    var pdpH = (bch - vbw);
    var pdpWH = Math.min(pdpW, pdpH);
    objPanelDivPower.style.width = pdpWH + 'px';
    objPanelDivPower.style.height = pdpWH + 'px';
  }

  if (objPanelDivClock) {
    var pdcW = gcw;
//  var pdcH = bch - goh - vbw;
    var pdcH = pdpWH - goh;
    objPanelDivClock.style.width = pdcW + 'px';
    objPanelDivClock.style.height = pdcH + 'px';

    var tWmin = 0;
    if (tempChannels != 0) {
      if (objGaugeDivTemp) {
        tWmin = 110;
      }
    } else {
      objGaugeDivTemp = null;
    }
  
    var tempOnLeft = 0;
    
    if (objGaugeDivClock) {
      var gdcW = pdcW - tWmin;
      var gdcH = pdcH - 0;
      var gdcWH = Math.min(gdcW, gdcH);
      var gdcLM = Math.floor((pdcW - gdcWH - tWmin) / 2);
      
      objGaugeDivClock.style.position = 'absolute';
      if (tempOnLeft) {
        objGaugeDivClock.style.left = tWmin + 'px';
      } else {
        objGaugeDivClock.style.left = gdcLM + 'px';
      }
      objGaugeDivClock.style.width = (gdcWH - 3) + 'px';
      objGaugeDivClock.style.height = (gdcWH - 3) + 'px';
    }
  
    if (objGaugeDivTemp) {
      var gdtW = tWmin - 10;
      var gdtH = gdcWH -3;   // clock height
//    var gdtH = pdcH - 3;   // full height
      var gdtLM = Math.floor((pdcW - gdcLM - gdcWH - gdtW - 16) / 2);
      objGaugeDivTemp.style.position = 'absolute';
      objGaugeDivTemp.style.top = '1px';
      if (tempOnLeft) {
        gdtH -= 30;
        objGaugeDivTemp.style.left = '0px';
      } else {
        objGaugeDivTemp.style.left = (gdcLM + gdcWH + gdtLM) + 'px';
//      objGaugeDivTemp.style.right = '10px';
      }
      objGaugeDivTemp.style.width = gdtW + 'px';
      objGaugeDivTemp.style.height = gdtH + 'px';
    }

  } // objPanelDivClock


  if (objGaugeDivPower) {
    var gdpW = objPanelDivPower.clientWidth - 3;
    var gdpH = objPanelDivPower.clientHeight - 3;
    var gdpWH = Math.min(gdpW, gdpH);
    objGaugeDivPower.style.height = gdpWH + 'px';
    objGaugeDivPower.style.width = gdpWH + 'px';
  }

  
  /* adjust link font-size */
  var objHomePageLinkDiv = document.getElementById('homePageLinkDiv');
  if (objHomePageLinkDiv) {
    objHomePageLinkDiv.style.fontSize = Math.floor(gdpWH / 35) + 'px';
  }

  /* adjust popup Options position */
  if (objGaugeDivClock) {
    if (objPopupDivOptions) {
      objPopupDivOptions.style.top = canvasTop(objGaugeDivClock) + 8 + 'px';
      objPopupDivOptions.style.left = canvasLeft(objGaugeDivClock) + 8 + 'px';
    }
  }

  /* adjust popup Ajax position */
  if (objGaugeDivPower) {
    if (objPopupDivAjax) {
      objPopupDivAjax.style.top = canvasTop(objGaugeDivPower) + 8 + 'px';
      objPopupDivAjax.style.left = canvasLeft(objGaugeDivPower) + 8 + 'px';
    }
  }

} /* resizeGauges */

var cntCanvasLeft = 0;
var cntCanvasTop = 0;

function canvasLeft(oElement) {
  cntCanvasLeft++;
  var offsetLeft = oElement.offsetLeft;
  if (oElement.offsetParent && cntCanvasLeft < 10)
    offsetLeft += canvasLeft(oElement.offsetParent);
//  else alert('canvasLeft: last element is: ' + oElement.tagName + '  cntCanvasLeft = ' + cntCanvasLeft);
  return offsetLeft;
}

function canvasTop(oElement) {
  cntCanvasTop++;
  var offsetTop = oElement.offsetTop;
  if (oElement.offsetParent && cntCanvasTop < 10)
    offsetTop += canvasTop(oElement.offsetParent);
//  else alert('canvasTop: last element is: ' + oElement.tagName + '  cntCanvasTop = ' + cntCanvasTop);
  return offsetTop;
}

function getRenderingMode() {
  var mode = document.compatMode;
  var m = 'unknown';
  if (mode) {
    if (mode == 'BackCompat')
      m = 'quirks'; 
    else if (mode == 'CSS1Compat')
      m = 'Standard'; 
    else
      m = 'Almost Standard'; 
    m += ' [' + mode + ']'
//  alert('The page is rendering in ' + m + ' mode.'); 
  } 
  return m;
} 


/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */


function windowOnload() {

  if (!(xhr = getXHR())) {
    alert('loadXHR(): XMLHttpRequest is not available');

  } else {

    objSplashScreen = document.getElementById('splashScreen');
    objLayoutTable = document.getElementById('layoutTable');
    objLayoutDiv = document.getElementById('layoutDiv');
    objPanelDivClock = document.getElementById('panelDivClock');
    objPanelDivPower = document.getElementById('panelDivPower');
    objPanelDivGraph = document.getElementById('panelDivGraph');
    objPopupDivOptions = document.getElementById('popupDivOptions');
    objPopupDivAjax = document.getElementById('popupDivAjax');
    objGaugeDivClock = document.getElementById('gaugeDivClock');
    objGaugeDivTemp = document.getElementById('gaugeDivTemp');
    objGaugeDivPower = document.getElementById('gaugeDivPower');
    objGraphImg = document.getElementById('plotPic');
    objSelGraphTimeRange = document.getElementById('selGraphTimeRange');

    selectedViewRangeIndex = parseInt('0' + selectedViewRangeIndex, 10);  /* make it numeric */
    objSelGraphTimeRange.selectedIndex = selectedViewRangeIndex;
    document.ajax.localStartTime.value = fmtDateTime(localStartTime);
    document.graphOptions.m.checked = (graphMarkers != 0) ? true : false;
    document.graphOptions.o.checked = (graphOrthogonal != 0) ? true : false;
    document.graphOptions.q.checked = (graphBgPower != 0) ? true : false;


  
    renderingMode = getRenderingMode();
  
    resizeGauges();
    loadGauges();
  
    initMovableDiv(objPopupDivOptions);
    initMovableDiv(objPopupDivAjax);

    if (objGraphImg != null) {
      addEvent(loadIMG, 'load', newGraphLoaded);
    }
  
    oldWindowWidth=document.body.offsetWidth;
    oldWindowHeight=document.body.offsetHeight;
//  addEvent(window, 'resize', windowResize);

    window.status = 'starting EMC';
    setTimeout(startEmc, 3000);

  }

} /* windowOnload() */

function startEmc() {
  if (objLayoutTable != null) {
    objLayoutTable.style.visibility='visible';
  }
  if (objSplashScreen != null) {
    objSplashScreen.style.display = 'none';
  }
  setTimers();
  window.status = '';
}


/* --------------------------------------------------------- */

var movableObjects=0;
var moveYstart=0;
var moveXstart=0;
var moveTopStart=0;
var moveLeftStart=0;
var objMoveObject=null;

function initMovableDiv(oDiv) {
  if (oDiv != null) {
    addEvent(oDiv, 'mousedown', startMovePanel);
    if (movableObjects == 0) {
      addEvent(document.body, 'mousemove', doMovePanel);
      addEvent(document.body, 'mouseup', endMovePanel);
    }
    movableObjects++;
  }
}

/* mousedown */
function startMovePanel(e) {
	var eve;
	if (!e) var e = window.event;                 // not needed for IE FF Chrome
	if (e.target) eve = e.target;                 // Firefox
	else if (e.srcElement) eve = e.srcElement;    // IE
	if (eve.nodeType == 3) // defeat Safari bug
		eve = eve.parentNode;
  objMoveObject = null;                         // disable moving
 	if (eve.tagName == 'DIV') {                   // no bubbles or captures
   	if (e.button == 0 || e.button == 1) {       // check left mousebutton, grr! 0=IE-left, 1=FF-left
      objMoveObject = eve;                      // enable moving
      moveYstart = e.screenY;
      moveXstart = e.screenX;
      moveTopStart = eve.offsetTop;
      moveLeftStart = eve.offsetLeft;
    }
  }
}

/* mousemove */
function doMovePanel(e) {
	var eve = objMoveObject;
	if (!e) var e = window.event;
	if (objMoveObject) {
    if (e.button == 0 || e.button == 1) {        // grr! 0=IE-left, 1=FF-left
  	  var x = e.screenX - moveXstart;
  	  var y = e.screenY - moveYstart;
    	eve.style.top = moveTopStart + y + 'px';
    	eve.style.left = moveLeftStart + x + 'px';
    }
	}
}

/* mouseup */
function endMovePanel(e) {
  objMoveObject = null;
}

/* --------------------------------------------------------- */

 addEvent(window, 'load', windowOnload);




