<!-- static attributes for all animations -->

    var stopBut = "stop.gif"
    var stopButR = "stopR.gif"
    var playBut = "play.gif"
    var playButR = "playR.gif"
    var noDot = "spacer.gif"
    var redDot = "red_spacer.gif"
    var missingImage = "spacer.gif"
    //var speedIndicator = "/weather/images/controls/speed"  + 1 to 15 + .gif
    var maxImgHeight = 1;
    var maxImgWidth = 1;

    var Delay = 800;     // Animation delay in ms
    var DelayStep = 100; // Delay step in ms
    var delay_max = 1600; // Max value for Delay
    var delay_min = 300; // Min value for Delay
    var StopFlag = 1;
	
<!-- end of static attributes -->

function Animator(animation) {
    if ( arguments.length > 0 )
        this.init(animation);
}

Animator.prototype.init = function(animation) {
    this.animation = animation;
};

// Updates symbol indicating current frame of animation on display
Animator.prototype.updateDots = function updateDots(n) {
	this.turnOffDots();
	this.animation.currentImageIndicator[n].src = redDot;
}

// Removes (blanks) all symbols for indicating current animation frame
Animator.prototype.turnOffDots = function() {
	for (var i=0; i<=this.animation.LastImg; i++) {
		this.animation.currentImageIndicator[i].src = noDot;
	}
}

// Displays the image according to which frame/link the user has clicked on
Animator.prototype.swapImg = function(n) {
	var obj = this;
	this.animation.ImageNum = n;
	if (!this.animation.theImages[this.animation.ImageNum]) {
    	this.updateImages(this.animation.ImageNum);
	}
	this.animation.timerID2=setTimeout(function(){obj.ChangeImg2(obj.animation.ImageNum)}, 50);
}

// Start (or restart) animation
Animator.prototype.Start = function() {
    //var obj = this;
    if (StopFlag == 1 ) {
        if (this.animation.loaded == false) {
		    this.loadAllImages();
		    this.waitUntilLoaded();  // once they're all loaded, this will start the animation
	    } else {
        StopFlag = 0;
        if (this.animation.stopButton) {this.animation.stopButton.src = stopBut}
		    if (this.animation.playButton) {this.animation.playButton.src = playButR}
		    this.Animate();
	    }
    }
    // expand on this to allow for refresh of stale images after some delay
    // to do to refactor animation properties into main animator. In fact it can die altogether
    // and just pass the array of images, counters etc in to the animator constructor.
    // also need to pass some unique arg to servlet to bypass web caching.
    // setTimeout(function(){obj.Start("foo")}, 7500); 
}

Animator.prototype.loadAllImages = function() {
	MM_showHideLayers('loading','','show');  //Display message to say 'loading in progress'
	for (var i=this.animation.FirstImg; i<=this.animation.LastImg; i++) {
		this.updateImages(i);
	}
}

Animator.prototype.updateImages = function(num) {
	
    var obj = this;
    this.animation.theImages[num] = new Image();
    this.animation.theImages[num].src = this.animation.imagePath+this.animation.imageName+(this.animation.FrameElement[num]);
	if (this.animation.FrameGust[num]) {
		this.animation.theGustImages[num] = new Image();
	    this.animation.theGustImages[num].src = this.animation.imagePath+(this.animation.FrameGust[num]);
	}
	if (this.animation.FrameNum[num]) {
		this.animation.theLabelImages[num] = new Image();
    	this.animation.theLabelImages[num].src = this.animation.labelImagePath+(this.animation.FrameNum[num]);
	}

// Think this bit isn't needed, as 'this' gets a loadHandler afterwards anyway. Seems to lead to 
// 'extra' count increments, which causes the animation to start playing before they're actually 
// all loaded. (HL, 06/09/2005)
// ***
// if the required item is already loaded,    
//    if (this.animation.theImages[num].complete) {
// increment the num loaded count 
//	    this.animation.numLoaded=this.animation.numLoaded+1;
////		setTimeout(function(){obj.Start("foo")}, 7500); 
//	}
// ***

// Added, then removed next bit 07/06/2005 as now unnecessary:
// ***
// Only set a load handler if a load handler has not already been assigned to an image. (HL, 06/09/2005)
//	if (this.animation.handlerAssigned[num] != true) {
// add onLoad callback (note closure - this (the Animator) is made in scope at closure execution by assigning 'this' to obj)
// imageLoadHandler will increment num loaded count once missing items are available.
//		this.animation.theImages[num].onload = function(){obj.imageLoadHandler()};
// Flag that this image 'num' has now been assigned a handler:
//		this.animation.handlerAssigned[num] = true;
//	}
// ***
}

// increment number of frames that have finished loading into the browser
//Animator.prototype.imageLoadHandler = function() {
//	//animated.numLoaded++;  
//  	this.animation.numLoaded=this.animation.numLoaded+1;
//}

Animator.prototype.waitUntilLoaded = function() {
  var obj = this;
  // Stay in this function until all the images have loaded, so we can start the animation
//	alert("Still loading "+this.animation.numLoaded+" "+eval(this.animation.LastImg*1.0+1)) // to check that numLoaded is never > LastImg+1 

	var notAllLoaded = false;
	var numLoaded = 0;
	for (var i=this.animation.FirstImg; i<=this.animation.LastImg; i++) {
//		alert(i+" "+this.animation.theImages[i].complete)
		if (this.animation.theImages[i].complete) {
			numLoaded++;
		} else {
			notAllLoaded = true;
		}
	}

// if all the images have loaded:
//	if (this.animation.numLoaded >= eval(this.animation.LastImg*1.0+1)) { // changed test condition to:
	if (!notAllLoaded) {
//		alert("Loaded "+this.animation.numLoaded+" "+eval(this.animation.LastImg*1.0+1)) // to check that numLoaded is never > LastImg+1 
//		alert(numLoaded+" "+eval(this.animation.LastImg*1.0+1))
		this.animation.loaded = true;
		MM_showHideLayers('loading','','hide');  //Hide message saying 'loading in progress'
		StopFlag = 0;
		if (this.animation.stopButton) {this.animation.stopButton.src = stopBut}
		if (this.animation.playButton) {this.animation.playButton.src = playButR}
		
		// preparation to show 'missing image' with same height as the product image:
		for (var i=this.animation.FirstImg; i<=this.animation.LastImg; i++) {
			if (this.animation.theImages[i].height > maxImgHeight) {
				maxImgHeight = this.animation.theImages[i].height
				maxImgWidth = this.animation.theImages[i].width
			}
		}
		
		this.Animate();
	} else {
		MM_setTextOfLayer('loading','','<strong>Please wait. Loaded '+numLoaded+' images out of '+eval((this.animation.LastImg-this.animation.FirstImg)*1.0+1)+'...</strong>')
	    setTimeout(function(){obj.waitUntilLoaded()}, 100); // slight pause to give more of the image(s) a chance to load
	}
}

// Animate images forward, loop continously
Animator.prototype.Animate = function() {

    var obj = this;
    this.animation.ImageNum=this.animation.actualImageNum;
    this.animation.ImageNum++;
    if(this.animation.ImageNum > this.animation.LastImg) { // this branch used if end of animation reached
        this.animation.ImageNum = this.animation.FirstImg;
        this.animation.timerID=setTimeout(function() {obj.ChangeImg(obj.animation.ImageNum)},Delay*3);
    } else { // this branch used if not at end of animation
        this.animation.timerID=setTimeout(function() {obj.ChangeImg(obj.animation.ImageNum)},Delay);
    }
}

Animator.prototype.ChangeImg = function(Num) {

	if (this.animation.theImages[Num]) {
		this.animation.currentImage.src = this.animation.theImages[Num].src
	}
	if (this.animation.FrameGust[Num]) {
		this.animation.currentGustImage.src = this.animation.theGustImages[Num].src
	}
	if (this.animation.FrameNum[Num]) {
		this.animation.currentLabelImage.src = this.animation.theLabelImages[Num].src
	}

	if (this.animation.theImages[Num].height > maxImgHeight) {
		maxImgHeight = this.animation.theImages[Num].height
		maxImgWidth = this.animation.theImages[Num].width
	}

	updateProgress(Num, days[Num]) 
	updateAltTags(Num)

	// Ensures that stepping the image after animating doesn't skip a frame due to the delay between 
    // incrementing ImageNum and displaying the image. ie. user could stop the image after ImageNum 
    // has incremented, but before the next frame has been displayed. 
    this.animation.actualImageNum = Num;
    this.Animate();
}

// Step image back one position (only if not animating)
Animator.prototype.StepBck = function() {
    var obj = this;
    this.animation.ImageNum = this.animation.actualImageNum;
    if(StopFlag == 1) {
        this.animation.ImageNum--;
        if(this.animation.ImageNum < this.animation.FirstImg) {
            this.animation.ImageNum = this.animation.LastImg;
        }
        this.updateSingleImage(this.animation.ImageNum);
        MM_showHideLayers('loading','','hide');
      	this.animation.timerID2=setTimeout(function(){obj.ChangeImg2(obj.animation.ImageNum)}, 50);
    }
}

// Step image forward one position (only if not animating)
Animator.prototype.StepFwd = function() {
    var obj = this;
    this.animation.ImageNum = this.animation.actualImageNum;
    if(StopFlag == 1) {
        this.animation.ImageNum++;
        if(this.animation.ImageNum > this.animation.LastImg) {
            this.animation.ImageNum = this.animation.FirstImg;
        }
        this.updateSingleImage(this.animation.ImageNum);
        MM_showHideLayers('loading','','hide');
      	this.animation.timerID2=setTimeout(function(){obj.ChangeImg2(obj.animation.ImageNum)}, 50);        
    }

}

Animator.prototype.SetImg = function(num) {
	var obj = this;
	if (num != null) {
		if (num < map.FirstImg) {num = map.FirstImg}
		this.animation.actualImageNum = num;
	    this.animation.ImageNum = this.animation.actualImageNum;
	} else {		
	    this.animation.ImageNum = this.animation.actualImageNum;
	}
	this.updateSingleImage(this.animation.ImageNum);
	MM_showHideLayers('loading','','hide');

	this.animation.timerID2=setTimeout(function(){obj.ChangeImg2(obj.animation.ImageNum)}, 50);        
	
}

Animator.prototype.updateSingleImage = function(num) {
    this.animation.theImages[num] = new Image();
    this.animation.theImages[num].src = this.animation.imagePath+this.animation.imageName+(this.animation.FrameElement[num]);
	if (this.animation.FrameGust[num]) {
		this.animation.theGustImages[num] = new Image();
	    this.animation.theGustImages[num].src = this.animation.imagePath+(this.animation.FrameGust[num]);
	}
	if (this.animation.FrameNum[num]) {
		this.animation.theLabelImages[num] = new Image();
    	this.animation.theLabelImages[num].src = this.animation.labelImagePath+(this.animation.FrameNum[num]);
	}

}

Animator.prototype.ChangeImg2 = function(Num) {

	if (this.animation.theImages[Num]) {
		this.animation.currentImage.src = this.animation.theImages[Num].src
	}
	if (this.animation.FrameGust[Num]) {
		this.animation.currentGustImage.src = this.animation.theGustImages[Num].src
	}
	if (this.animation.FrameNum[Num]) {
		this.animation.currentLabelImage.src = this.animation.theLabelImages[Num].src
	}
//    this.updateDots(Num);	
	updateProgress(Num, days[Num]) 
	updateAltTags(Num)
		
    // Ensures that stepping the image after animating doesn't skip a frame due to the delay between 
    // incrementing ImageNum and displaying the image. ie. user could stop the image after ImageNum 
    // has incremented, but before the next frame has been displayed. 
    this.animation.actualImageNum = Num;
}


// Stop animation
Animator.prototype.Stop = function() {
    if (StopFlag == 0) {
        StopFlag = 1;
        if (this.animation.playButton) {this.animation.playButton.src = playBut}
        if (this.animation.stopButton) {this.animation.stopButton.src = stopButR}
        clearTimeout(this.animation.timerID);
    }
}

Animator.prototype.change_speed = function(factor) {
    //===> changes playing speed by adding to or subtracting from the delay between frames
    var ds = DelayStep;
    ds*=factor;
    Delay+=ds;
    if(Delay > delay_max) Delay = delay_max;
    if(Delay < delay_min) Delay = delay_min;
    // speed indicator has 16 steps:
   	var speed_str = 17 - Delay/100;
	  if (this.animation.speed) {this.animation.speed.src = speedIndicator+speed_str+".gif"}
//	  alert("1: "+speed_str+" "+this.animation.Delay/100)
}

Animator.prototype.slowDown = function() {
    // Slow down the animation
    this.change_speed(1);
}

Animator.prototype.speedUp = function() {
    // Speed up the animation
    this.change_speed(-1);
}

// Go to first image in sequence
// (Not currently used)
Animator.prototype.gotoFirst = function() {
    this.animation.ImageNum = this.animation.actualImageNum;
    if(StopFlag == 1) {
        this.animation.ImageNum = 0;
      	this.animation.timerID2=setTimeout(function(){obj.ChangeImg2(obj.animation.ImageNum)}, 50);
    }
}

// Go to first image in sequence
// (Not currently used)
Animator.prototype.gotoLast = function() {
    this.animation.ImageNum = this.animation.actualImageNum;
    if(StopFlag == 1) {
        this.animation.ImageNum = this.animation.LastImg;
      	this.animation.timerID2=setTimeout(function(){obj.ChangeImg2(obj.animation.ImageNum)}, 50);
    }
}