<!-- radar.loop.v02.js -->
<!-- Below is the Radar Loop code plus cursor Pointer & Origin code.-->
<!-- 010507 Clive Edington, Better logic for browser version vs actions.-->
<!-- 001207 Clive Edington, No html here, just js.  Allow No images.-->
<!-- 000728 Clive Edington, generalised the code for www.bom.gov.au-->
<!-- 000728 Mike Fewings, Modified for radar.strikeone.net.au and satellite pics-->
<!-- Thanks to Alf West and the Radar Section for the original code.-->

<!--
// Usage:
// (1) Call 'launch()' once (e.g. from BODY onload="..") to start this code.
// (2) Assumes that these Image dependent variables have already been defined:
//
// Km = nn;	// Standard 64km, 128km, 256km or 512km radar picture.
// nImages = n;
// tINm = new Array();
// tINm[0] = "filename1.gif";
// tINm[1] = "filename2.gif";
// ...etc...
// -----------------------------------------------------------------

// If there are some images, loop them.
// else when no images are available, exit now.
//	Assume that the enclosing html will provide a message.

// 
// Microsoft vs. Netscape.  See below for safer definitions.
// If either of these are true, then the mouse-distances (cursor) shows.
// If both false, then we get simple loops, but no mouse.
  isMS = false;
  isNN = false;
  isNN6 = false;
  isCursor = false;
  var d = window.document;
  if (navigator.appName.indexOf("Microsoft") != -1) {
    if (parseFloat(navigator.appVersion) >= 4.) isMS = true;
  }   
  if (navigator.appName.indexOf("Netscape") != -1) {
    // Netscape 6 reports v5 !!!
    if  ( (parseFloat(navigator.appVersion) >= 4.) && (parseFloat(navigator.appVersion) < 5.) ) isNN = true;
    if  ( (parseFloat(navigator.appVersion) >= 5.) && (parseFloat(navigator.appVersion) < 6.) ) isNN6 = true;
  }   


if (nImages>0) { 

  var doc;	// Holds a pointer to MS or NN document (see launch).
  
// Now the general Looping code.
//
//============================================================
//                >> jsImagePlayer 1.0 <<
//            for Netscape3.0+, September 1996
//============================================================
//                  by (c)BASTaRT 1996
//             Praha, Czech Republic, Europe
//
// feel free to copy and use as long as the credits are given
//          by having this header in the code
//
//          contact: xholecko@sgi.felk.cvut.cz
//          http://sgi.felk.cvut.cz/~xholecko
//
//============================================================
// Thanx to Karel & Martin for beta testing and suggestions!
//============================================================
//
//     modified by D. Watson and A. Earnhart (CIRA/CSU), 7/30/97
//     and Greg Thompson (NCAR/RAP) Dec. 11 1997

// step 1: define the images
//		See "tINm" set above.
 
//
// step 2: define variables used to control images
//

image_href = "";
fI = 0;
lI = nImages-1;
enableGraphUpdate=1;
//
// step 3: define dimensions of image (would be nice if this were interactively done)
//         Presently these ARE NOT used below. See step 9
//

aH  = 524;
aW  = 564;
 
//**************************************************************************
 
//=== THE CODE STARTS HERE - no need to change anything below ===
 
//=== global variables ====

tImg = new Array();      //holds the images
imgn = new Array();       //keeps track of which images to omit from loop
nDl = 300;
dL = nDl;         //dL between frames in 1/100 seconds
dMx = 645;
dMn = 20;
dSt = 25;
sSt = 25;
dSt = Math.floor((dMx - dMn )/ sSt);
tCs = sSt-Math.floor(dL/dSt);
dwm = 3;
dws = 1;
eDM   = dwm;
sDM = dwm - 1;

cI = fI;     //number of the current image
timeID = null;
radarStatus = 0;                      // 0-stopped, 1-playing
play_mode = 0;                   // 0-normal, 1-loop, 2-sweep
size_valid = 0;
 
}  // (end of if there are images to loop)

function Prelaunch()
{
fI = 0;
lI = nImages-1;
enableGraphUpdate=1;
cI = fI;     //number of the current image
timeID = null;
tImg.length = 0;
imgn.length = 0;
launch(1);

}

//===> Load and initialize everything once page is downloaded (called from 'onLoad' in <BODY>)

function launch(origin)
{
  if (nImages==0)  return;

  if (isCursor)  startxy ();	// Start pointer-origin code.
  
   //display image number
   ld = new Date(tITm[nImages-1]);
    //alert(scan_date.getDate() );
   // format hours for am pm
    var ampm="am";
   if (ld.getHours()>=12||ld.getHours()==0) {
        hours=Math.abs(ld.getHours()-12);
        if(hours==0) {hours=12;}
        if (ld.getHours()!=0) {
            ampm="pm";
        }
    }
    else {
        hours=ld.getHours();
    }

   
   d.getElementById("lasttime").innerHTML = " "+hours+":"+(ld.getMinutes()<10?"0"+ld.getMinutes():ld.getMinutes())+" "+ampm+"";

  
  doc = document;
  d.getElementById('currentSpeed').innerHTML ="("+tCs+"/"+sSt+")";
  if (isNN) doc = document.animationlayer.document;
  // If there is only 1 image, show it, but dont start the loop.
  if (nImages==1) {
    cI = 0;
    tImg[cI] = new Image(aW,aH);
    tImg[cI].src = image_href + tINm[cI];
    imgn[cI] = true;   // pretend it is ready.
    display_cI();
    return;
  }
    
  
  //
  // step 5: construct filenames for all images 
  //
  for (var i = fI; i <= lI; i++)
  {
    cI = i;
    tImg[cI] = new Image(aW,aH);
    tImg[cI].src = image_href + tINm[cI];
    imgn[cI] = false;  // image is not ready yet.
  }
  cI = fI;
  imgn[cI] = true;   // pretend it is ready.
 
  // this needs to be done to set the right mode when the page is manually reloaded
  if(!origin) {change_mode (1);fwd();}
  
}
 
function display_slider()
{
    stop();
    cI = document.control_form.frame_nr.value-1;
    display_cI();
}

function display_cI()
{
   //display image onto screen
   doc.animation.src = tImg[cI].src;
   //display image number
   document.control_form.frame_nr.value = cI+1;
   document.control_form.frame_nr.value = cI+1;
   sd = new Date(tITm[cI])
    //alert(scan_date.getDate() );
   // format hours for am pm
    var ampm="am";
   if (sd.getHours()>=12||sd.getHours()==0) {
        hours=Math.abs(sd.getHours()-12);
        if(hours==0) {hours=12;}
        if (sd.getHours()!=0) {
            ampm="pm";
        }
    }
    else {
        hours=sd.getHours();
    }
   positionSliderImage(false,1);
   d.getElementById("localtime").innerHTML = "<strong> "+hours+":"+(sd.getMinutes()<10?"0"+sd.getMinutes():sd.getMinutes())+" "+ampm+"</strong> ";
   d.getElementById("loopnumber").innerHTML = "<strong>"+eval(cI+1)+"</strong>";
}
 
//===> Stop the animation

function stop()
{
//== cancel animation (timeID holds the expression which calls the fwd or bkwd function) ==
//alert(radarStatus);
  if (radarStatus == 1) {
    clearTimeout (timeID);
  }
  radarStatus = 0;
  return;
}

//===> Display animation in fwd direction in either loop or sweep mode

function animate_fwd()
{
   if (nImages<=1) return;
   cI++;                      //increment image number
 
  //== check if current image has exceeded loop bound ==
  if (cI > lI) {
    if (play_mode == 1) {              //fwd loop mode - skip to first image
      cI = fI;
    }
    if (play_mode == 2) {              //sweep mode - change directions (go bkwd)
      cI = lI;
      animate_rev();
      return;
    }
    //alert ("radarStatus "+  radarStatus);
  }
 
  //== check to ensure that current image has not been deselected from the loop ==
  //== if it has, then find the next image that hasn't been ==
  while (imgn[cI] == false) {
    if (tImg[cI].complete) {
        imgn[cI] = true;
        break;
    }
    cI++;
    if (cI > lI) {
      if (play_mode == 1)
        cI = fI;
      if (play_mode == 2) {
        cI = lI;
        animate_rev();
        return;
      }
    }
  }
 
  display_cI();

  dTm = dL;
  if (cI == fI)  dTm = sDM*dL;
  if (cI == lI)   dTm =   eDM*dL;
 
  //== call "animate_fwd()" again after a set time (dTm) has elapsed ==
  timeID = setTimeout("animate_fwd()", dTm);
}
 
 
//===> Display animation in reverse direction

function animate_rev()
{
  if (nImages<=1) return;
  cI--;                      //decrement image number
 
  //== check if image number is before lower loop bound ==
  if (cI < fI) {
    if (play_mode == 1) {               //rev loop mode - skip to last image
       cI = lI;
    }
    if (play_mode == 2) {
      cI = fI;     //sweep mode - change directions (go fwd)
      animate_fwd();
      return;
    }
  }
 
  //== check to ensure that current image has not been deselected from the loop ==
  //== if it has, then find the next image that hasn't been ==
  while (imgn[cI] == false) {
    if (tImg[cI].complete) {
        imgn[cI] = true;
        break;
    }
    cI--;
    if (cI < fI) {
      if (play_mode == 1)
        cI = lI;
      if (play_mode == 2) {
        cI = fI;
        animate_fwd();
        return;
      }
    }
  }
  
  display_cI();

  dTm = dL;
  if (cI == fI)  dTm = sDM*dL;
  if (cI == lI)   dTm =   eDM*dL;
 
  //== call "animate_rev()" again after a set amount of time (dTm) has elapsed ==
  timeID = setTimeout("animate_rev()", dTm);
}

//===> Changes playing speed by adding to or substracting from the dL between frames
function change_speed(dv)
{
  dL+=dv;
  //== check to ensure max and min dL constraints have not been crossed ==
  if(dL > dMx) dL = dMx;
  if(dL < dMn) dL = dMn;
  tCs = sSt-Math.floor(dL/dSt);
  d.getElementById('currentSpeed').innerHTML ="("+tCs+"/"+sSt+")";
}
 
//===> functions that changed the dwell rates.

function change_end_dwell(dv) {
  eDM+=dv;
  if ( eDM < 1 ) eDM = 0;
}
 
function change_start_dwell(dv) {
  sDM+=dv;
  if ( sDM < 1 ) sDM = 0;
}
 
//===> Increment to next image

function incrementImage()
{
  var number;
  if (nImages<=1) return;
  stop();
  cI++;
  number = cI;

  //== if image is last in loop, increment to first image ==
  if (number > lI) number = fI;

  //== check to ensure that image has not been deselected from loop ==
  while (imgn[number] == false) {
    if (tImg[number].complete) {
        imgn[number] = true;
        break;
    }
    number++;
   if (number > lI) number = fI;
  }
 
  cI = number;
  display_cI();
}
 
//===> Decrement to next image

function decrementImage()
{
  var number;
  if (nImages<=1) return;
  stop();
  cI--;
  number = cI;
 
  //== if image is first in loop, decrement to last image ==
  if (number < fI) number = lI;
 
  //== check to ensure that image has not been deselected from loop ==
  while (imgn[number] == false) {
    if (tImg[number].complete) {
        imgn[number] = true;
        break;
    }
    number--;
   if (number < fI) number = lI;
  }
 
  cI = number;
  display_cI();
}
 
// captures a key stroke of forwards and backwards and moves the animation forwards or backwards

function stepThrough(ev)
{
    if (!document) {
		return false;
	}

    if (!(ev.ctrlKey || ev.altKey)) {
        switch (ev.keyCode) {
            case 37: // KEY left
                decrementImage();
            break;
            case 39: // KEY right
                incrementImage();
            break;
            case 190: // KEY '.' or '>'
                change_speed(-dSt);
            break;
            case 188: // KEY ',' or '<'
                change_speed(dSt);
            break;
            default:
            return true;
        }
    }

}

//===> "Play forward"

function fwd()
{
  stop();
  radarStatus = 1;
  play_mode = 1;
  animate_fwd();
}
 
//===> "Play reverse"

function rrev()
{
  stop();
  radarStatus = 1;
  play_mode = 1;
  animate_rev();
}

//===> "play sweep"

function sweep() {
  stop();
  radarStatus = 1;
  play_mode = 2;
  animate_fwd();
}
 
//===> Change play mode (normal, loop, swing)

function change_mode(mode)
{
   play_mode = mode;
}
 
//===> Check selection status of image in animation loop
function checkImage(radarStatus,i)
{
  if (radarStatus == true)
    imgn[i] = false;
  else imgn[i] = true;
}
 
//==> Empty function - used to deal with image buttons rather than HTML buttons
function func()
{
}
 
<!-- Below is the Radar moving cursor Pointer & Origin code.-->
<!-- 000728 Clive Edington, generalised the code.-->
<!-- Thanks to Alf West and the Radar Section for the original code.-->

  // Usage:
  // (1) Call 'startxy()' once (e.g. from BODY onload="..") to start this code.
  // (2) Assumes that these Image dependent variables have already been defined:
  //
  // GifFileName = "??.gif";
  // Km = nn;	// Standard 64km, 128km, 256km or 512km radar picture.
  // -----------------------------------------------------------------
  //
  // This code assumes a TABLE with a radar image and X, Y outputs, etc,
  // and then does the logic of updating X & Y whenever the mouse moves.
if (nImages>0) {
  // Compute some internal globals.
  var maxKm = Km-1;
  //  128km is .5 KmPerPixel,  512km is 2 KmPerPixel
  var KmPerPixel = Km/256;
 
  // Internal Global variables.
  var xx=0;
  var yy=0;
  var zz=0;
  var aa=0;
  var xKm=0;
  var yKm=0;
  var xKmOrigin=0;
  var yKmOrigin=0;
}


// startxy is called once after the BODY has been loaded.
//	It initalises x-y stuff and sets up mouse-event-callbacks.
//
function startxy ()
{
  // Setup mouse-move & mouse-click(down) callbacks.
  if (isMS || isNN6) {
    document.body.onmousemove=move;
    document.body.onmousedown=downimage;
    //document.animation.src = GifFileName;
  }
  if (isNN) {
    document.captureEvents(Event.MOUSEMOVE);
    document.onMouseMove=move;
    document.captureEvents(Event.MOUSEDOWN);
    document.onMouseDown=downimage;
    //window.onresize = resize;  // Not needed because the loop will reload it.
    //document.animationlayer.document.animation.src = GifFileName;
  }
  resetOrigin ();
}

function stopxy ()
{
  // Setup mouse-move & mouse-click(down) callbacks.
  if (isMS || isNN6) {
    document.body.onmousemove=null;
    document.body.onmousedown=null;
    //document.animation.src = GifFileName;
  }
  if (isNN) {
    document.captureEvents(null);
    document.onMouseMove=null;
    document.captureEvents(null);
    document.onMouseDown=null;
  }
  resetOrigin ();
}

// Netscape-only (maybe Xterms only), reload the image after a resize.
function resize () {
      document.animationlayer.document.animation.src = GifFileName;
}

function move(e)	// When the mouse moves, update the pointer boxes.
{
    if (isMS) {
	e = window.event;
        // X-Y relative to the container (i.e. the image).
        xKm=9999;
        yKm=9999;
        if (e.srcElement && e.srcElement.name) {
          if (e.srcElement.name == "animation") {
            xKm= (e.offsetX-262+2)*KmPerPixel;
            yKm=-(e.offsetY-262+2)*KmPerPixel;
          }
        } 
    }
    if (isNN || isNN6) {
        xKm=9999;
        yKm=9999;
        if (e.target.name) {
          if (e.target.name == "animation") {
              if(isNN6) {
         //alert("here"+e.clientX+"here"+d.getElementById("animationlayer").offsetParent.offsetTop);
                   // xKm= (e.clientX - document.animationlayer.offsetX-262)*KmPerPixel;
                   // yKm=-(e.clientY - document.animationlayer.pageY-262)*KmPerPixel;
         //alert("here"+xKm+"here"+yKm);

             }
              else {
                  //  xKm= (e.pageX-document.animationlayer.pageX-262)*KmPerPixel;
                  //  yKm=-(e.pageY-document.animationlayer.pageY-262)*KmPerPixel;
              }
          }
        } 
    }

    if (Math.abs(xKm)>maxKm || Math.abs(yKm)>maxKm) {
      d.getElementById("xoffset").innerHTML ="&nbsp;"; 
      d.getElementById("yoffset").innerHTML ="&nbsp;";
      d.getElementById("zoffset").innerHTML ="&nbsp;";
      d.getElementById("aoffset").innerHTML ="&nbsp;";     
    }
    else {
      xx=xKm-xKmOrigin;
      yy=yKm-yKmOrigin;
      zz=Math.round(Math.sqrt(xx*xx+yy*yy)-.01);
      aa=450-Math.round(Math.atan2(yy,xx)*57.29);
      if (aa>359) { aa=aa-360; }
      if (zz<1)   { aa="0";    }

      xx=Math.round(xx);
      yy=Math.round(yy);
      xxs=xx+'';
      yys=yy+'';
      aas=aa+'';
      zzs=zz+'';
      paddingxx=xxs.length==1?"&nbsp;&nbsp;&nbsp;":xxs.length==2?"&nbsp;&nbsp;":"&nbsp;";
      paddingyy=yys.length==1?"&nbsp;&nbsp;":yys.length==2?"&nbsp;&nbsp;":"&nbsp;";
      paddingaa=aas.length==1?"&nbsp;&nbsp;&nbsp;":aas.length==2?"&nbsp;&nbsp;":"&nbsp;";
      paddingzz=zzs.length==1?"&nbsp;&nbsp;&nbsp;":zzs.length==2?"&nbsp;&nbsp;":"&nbsp;";
      
      if (xx>=0) d.getElementById("xoffset").innerHTML = '<b>'+ xx + paddingxx + '</b>Km East';
      else       d.getElementById("xoffset").innerHTML = '<b>'+ -xx + paddingxx + '</b>Km West';
      if (yy>=0) d.getElementById("yoffset").innerHTML =  '<b>'+ yy + paddingyy + '</b>Km North';
      else       d.getElementById("yoffset").innerHTML = '<b>'+ -yy + paddingyy + '</b>Km South';
      d.getElementById("zoffset").innerHTML = '<b>'+ zz + paddingzz + '</b>Km Away';
      d.getElementById("aoffset").innerHTML = '<b>'+ aa + paddingaa + '</b>Degrees';        
    }
}

function resetOrigin () 
{
   xKm = 0;
   yKm = 0;
   downimage();
}

function downimage()		// A left-click (mouse-down) to move the Origin. 
{
    // xKm & yKm are the distances from the centre of the radar image.
    // They were already computed in (mouse) move() above.
    // (or are zero at startup.)
    
    // Maybe set the new origin.
    if (Math.abs(xKm)<maxKm && Math.abs(yKm)<maxKm) {
        xKmOrigin=xKm;
        yKmOrigin=yKm;
    }
        
    xo = Math.round(xKmOrigin);
    xos=xo+'';
    yo = Math.round(yKmOrigin);
    yos=xo+'';
    paddingxo=xos.length==1?"&nbsp;&nbsp;&nbsp;":xos.length==2?"&nbsp;&nbsp;":"&nbsp;";
    paddingyo=yos.length==1?"&nbsp;&nbsp;":yos.length==2?"&nbsp;&nbsp;":"&nbsp;";


    if (xKmOrigin>=0) { d.getElementById("xpointoffset").innerHTML =  '<b>'+ xo + paddingxo +  '</b>Km&nbsp;&nbsp;East'; }
    else              { d.getElementById("xpointoffset").innerHTML = '<b>'+ -xo + paddingxo +  '</b>Km&nbsp;&nbsp;West'; }
    if (yKmOrigin>=0) { d.getElementById("ypointoffset").innerHTML =  '<b>'+ yo + paddingyo +  '</b>Km&nbsp;North';  }
    else              { d.getElementById("ypointoffset").innerHTML = '<b>'+ -yo + paddingyo +  '</b>Km&nbsp;South';  }
}

 
// Empty function - used to deal with image buttons rather than HTML buttons
function xynullfunc()
{
}

// Turn on and off the distance calculator 
function toggleDistance()
{
      if(isCursor) { isCursor= false; stopxy(); d.getElementById("turnoffon").innerHTML = 'Enable'; togAWScir(1); }
      else {   if (isMS || isNN || isNN6) { isCursor = true; } startxy (); d.getElementById("turnoffon").innerHTML = 'Disable'; togAWScir(0); }

}


function addEvent(el, evname, func) {
    if (el.attachEvent) { // IE
        el.attachEvent("on" + evname, func);
    } else if (el.addEventListener) { // Gecko / W3C
        el.addEventListener(evname, func, true);
    } else {
        el["on" + evname] = func;
    }
}

// add keystroke listeners to the document
addEvent(document, "keydown", stepThrough);
//addEvent(document, "keypress", stepThrough);
//addEvent(document, "mousedown", Calendar._checkCalendar);



function startLRmouseMove ()
{
    //stopxy ();
  if (isMS || isNN6) {
    lastX=0;
    document.body.onmousemove=leftRight;
    document.body.onmousedown=stopLRmouseMove;
  }
  if (isNN) {
    document.captureEvents(Event.MOUSEMOVE);
    document.onMouseMove=leftRight;
    document.captureEvents(Event.MOUSEMOVE);
    document.onMouseDown=stopLRmouseMove;
  }
}

function stopLRmouseMove ()
{
  if (isMS || isNN6) {
    document.body.onmousemove=null;
    document.body.onmousedown=null;
  }
  if (isNN) {
    document.captureEvents(null);
    document.onMouseMove=null;
    document.captureEvents(null);
    document.onMouseDown=null;
  }
}

function leftRight(e)	// When the mouse moves, update the pointer boxes.
{
    if (isMS) {xCoord=event.x} else if (isNN || isNN6) {xCoord=e.pageX;}else{xCoord=0;}

    if(xCoord>lastX+15) { if(cI+1<=lI){incrementImage();}lastX=xCoord;}

    else if(xCoord<lastX-15) { if(cI-1>=fI){decrementImage();}lastX=xCoord;}
}





function cPopUp(awsName) {
    openpopup(awsName,getWindowHtml(awsName),600,200,320,260,0,0,1,1); 
    populateData(awsName);
}

function wTInfoP(awsName,line1,line2,line3,displ) {
    d.getElementById('instL1').innerHTML = displ==1 ? '<strong>'+awsName+'</strong>' : '<strong>&nbsp;&nbsp;</strong>'; 
    d.getElementById('instL2').innerHTML = displ==1 ? line1 : 'Move your mouse over the'; 
    d.getElementById('instL3').innerHTML = displ==1 ? line2 : 'radar scan to find obs. data';    
    d.getElementById('instL4').innerHTML = displ==1 ? line3 : '...&nbsp;';
}


// courtesy of BOM http://mirror.bom.gov.au/products/IDR.loop.v08.js

function getRounded(num)
{
   num = Math.round(num)/100;
   // Turn -0 into +0
   if (num == 0) { num=Math.abs(num); }
      return num;
}


function getMapX(lon, xKm, yKm, mapy)
{
   mapx=100*lon+xKm/(1.1111*Math.cos(mapy/5729));
   return mapx;
}

function getMapY(lat, yKm)
{
   mapy=100*lat+yKm/1.1111;
   return mapy;
}


//-->

