// *******************
// TimeControl Class 
// *******************

/*
*** REMARK ***
Only 1 instance per document (event handlers are bound to instance name oTimeControl)
Instance must be called 'oTimeControl', i.e. oTimeControl = new TimeControl();

*** RESERVED ID IN DOM:
//TCoHTMLtimeControl
//TCoDate
//TCoTime
//TCoSpeed
//TCoDragButtonFine
//TCoDragButtonCoarse
//TCoDragButtonPlayback

*** DEPENDEND ON: * Thread.js
		  * globals.js

*** INTERFACE METHODS ***

setPosition()			//abs. postion of the widget
setVisibility()			//show/hide the widget
getTime
setTime()			//set time
stopPlayback()				//stop playback
setLockNav			//stop events from navigation and gfx disable ctrls
getLockNav			//getter method - is navigation locked or not?
htmlify();			//WARNING: new html presentation - must implement the necessary id's
destroy()			//call before removing object!

//-->event hooks
onChangeTime			//fires when control time is altered for some reason

onFirstImage()			//navigation
onPreviousSequence()		//controls
onPreviousImage()		//implented
onNextImage()			//as
onNextsequence()		//pure
onLatestImage()			//virtuals.

onPlaybackStart			//fire when playback
onPlaybackStop			//controls are accessed

onKnobDragStart			//fires when knob
onKnobDragStop			//controls are accessed

*/


function TimeControl() {
	this.m_loopBackTime = 0;
	this.someSessionId = document.uniqueID;			//get a unique id

	//general control props
	this.m_time = new Date();
	this.m_isLocked=false;

	this.m_position   = {x:300, y:300};						//control dimensions
	this.m_dimension = {width:287, height:226};				//control dimensions
	this.m_padding   = {left:44, right:44, top:0, bottom:0};	//slider paddings

	this.m_maxSpeedAtRadius=58;

	//display props
	this.m_pulseCounter = 0
	this.m_cUpdateDisplayThreshold = 5;

	this.m_years		= 0;
	this.m_months		= 0;
	this.m_days			= 0;

	this.m_hours		= 0;
	this.m_mins			= 0;
	this.m_secs			= 0;
	this.m_milliSecs	= 0;
	
  //

	//fine knob props
	this.m_cFineKnobWidth			= 22;		//8 pixels wide
	
	this.m_isDraggedFine			= false;
	this.m_initFineCoors			= {x:132,y:120};		//init. center fine knob coors
	this.m_fineVel				= {vx:0,vy:0};		//fine knob velocity vector
	this.cFineSpringConst			= 0.2;
	this.cFineEnergyLossFactor		= 0.8;
	this.oFineThread			= new Thread(this, 20);

	this.m_fineSlaggRadius = 10;
	this.m_minFineSpeedV=10;
	this.m_maxFineSpeedV=500;
	this.m_fineSpeedSlope=Math.log(this.m_maxFineSpeedV/this.m_minFineSpeedV)/this.m_maxSpeedAtRadius;

	//coarse knob props
	this.m_cCoarseKnobWidth				= 22;		//8 pixels wide

	this.m_isDraggedCoarse				= false;
	this.m_initCoarseCoors				= {x:132,y:145};		//init. center coarse knob coors
	this.m_coarseVel				= {vx:0,vy:0};		//coarse knob velocity vector
	this.cCoarseSpringConst				= 0.2;
	this.cCoarseEnergyLossFactor			= 0.8;
	this.oCoarseThread				= new Thread(this, 20);

	this.m_coarseSlaggRadius = 10;
	this.m_minCoarseSpeedV=500;
	this.m_maxCoarseSpeedV=50000;
	this.m_coarseSpeedSlope=Math.log(this.m_maxCoarseSpeedV/this.m_minCoarseSpeedV)/this.m_maxSpeedAtRadius;

	//PlaybackKnob props
	this.m_cPlaybackKnobWidth			= 22;												//8 pixels wide

	this.m_isDraggedPlayback			= false;
	this.m_initPlaybackCoors			= {x:132,y:174};										//init. center coarse knob coors

	this.m_playbackSlaggRadius 			= 4;
	this.m_velocitySpeedUpFactor			= 1;												//initial playback rate (1='normal' speed)
	this.m_maxPlaybackFactor			= 19;												//times normal playback speed

	//playback props
	this.m_beaconPeriode				= 40;												//25 frames
	this.m_advanceTime					= this.m_beaconPeriode;
	this.m_playDirection				= 1;												//1=time forward, -1 = time backwards
	this.m_isPlaybackEnabled			= false;

	this.oPlaybackThread				= new Thread(this, this.m_beaconPeriode, "pulse");

	//nav control pros
	this.m_isNavEnabled					= true;
	//setup HTML control
	
	if(typeof(document.body) == 'undefined') alert("document.body is undefined");
	else {
		var oNode = document.createElement("div");
    oNode.style.padding = "0px";
    oNode.style.borderStyle = "none";
    oNode.style.borderWidth = "0px";
		oNode.innerHTML =  this.htmlify();
		document.body.appendChild(oNode);
		
		//control props
		oNode.style.position = "absolute";
		oNode.style.left = this.m_position.x;
		oNode.style.top = this.m_position.y;

		oNode.style.width = this.m_dimension.width;
		oNode.style.height = this.m_dimension.height;

		//TCoHTMLtimeControl props
		document.all["TCoHTMLtimeControl"].style.width = this.m_dimension.width;
		document.all["TCoHTMLtimeControl"].style.height = this.m_dimension.height;

		//TCoDragButtonFine props
		document.all["TCoDragButtonFine"].style.left = this.m_initFineCoors.x;
		document.all["TCoDragButtonFine"].style.top  = this.m_initFineCoors.y;
				
		//TCoDragButtonCoarse props
		document.all["TCoDragButtonCoarse"].style.left = this.m_initCoarseCoors.x;
		document.all["TCoDragButtonCoarse"].style.top  = this.m_initCoarseCoors.y;

		//TCoDragButtonPlayback props
		document.all["TCoDragButtonPlayback"].style.left = this.m_initPlaybackCoors.x;
		document.all["TCoDragButtonPlayback"].style.top  = this.m_initPlaybackCoors.y;	
	}
}
TimeControl.prototype.constructor = TimeControl;

//*** PUBLIC INTERFACE METHODS ***
TimeControl.prototype.setPosition = function(x,y) {				//abs. postion of the widget
	document.all["TCoHTMLtimeControl"].parentNode.style.top=y;
	document.all["TCoHTMLtimeControl"].parentNode.style.left=x;
}
TimeControl.prototype.setVisibility = function(isVisible) {			//show/hide the widget
	if(isVisible) {
    document.all["TCoHTMLtimeControl"].style.visibility = "visible";
    document.all["TCoHTMLtimeControl"].parentNode.style.zIndex = "0";
  }
	else {
    document.all["TCoHTMLtimeControl"].style.visibility = "hidden";
    document.all["TCoHTMLtimeControl"].parentNode.style.zIndex = "-1";
  }
}
TimeControl.prototype.getTime = function() {					//set time
	return this.m_time;
}
TimeControl.prototype.setTime = function(oDate) {				//set time
	this.m_time = oDate;
	//force update of display
	this.updateDisplay();
}
TimeControl.prototype.stopPlayback = function() {					//stop playback
	this.stop();
}
TimeControl.prototype.setLockNav = function(bDoLock) {
	if(bDoLock && this.getIsNavEnabled() ) {	//wanna lock nav.
		this.setIsNavEnabled(false);		//stop all mess. from ctrl
		this.showNavigation(false);
	}
	else if(!bDoLock && !this.getIsNavEnabled() ) {	//wanna unlock nav.
		this.setIsNavEnabled(true);			//stop all mess. from ctrl
		this.showNavigation(true);
	}
}
TimeControl.prototype.getLockNav = function(bDoLock) {
	return !(this.getIsNavEnabled());
}
TimeControl.prototype.showNavigation = function(bShow) {
	var strExt;
	if(bShow) strExt = "off.jpg";
	else strExt="locked.jpg";
	
	document.all["TCoNavFirstImg"].src = "img/firstImage_"+strExt;
	document.all["TCoNavPreSeq"].src = "img/previousSequence_"+strExt;
	document.all["TCoNavPreImg"].src = "img/previousImage_"+strExt;
	document.all["TCoNavNxtImg"].src = "img/nextImage_"+strExt;
	document.all["TCoNavNxtSeq"].src = "img/nextSequence_"+strExt;
	document.all["TCoNavLatestImg"].src = "img/latestImage_"+strExt;
}
TimeControl.prototype.destroy = function() {
	(this.oFineThread).stop();
	TCoDragButtonFine.style.left=this.m_initFineCoors.x;
	(this.oCoarseThread).stop();
	TCoDragButtonCoarse.style.left=this.m_initCoarseCoors.x;
	this.stop();
	TCoDragButtonPlayback.style.left = this.m_initPlaybackCoors.x;
}
TimeControl.prototype.htmlify = function() {
	var strHTML = '<div id="TCoHTMLtimeControl" style="BACKGROUND-IMAGE: url(img/timenav_background.gif);POSITION: absolute; TOP: 0px;LEFT: 0px; padding:0px; border-style:none; border-width:0px; " onmousemove="oTimeControl.onMouseMove(event);" onmouseup="oTimeControl.onMouseUp(event);">';
		//*** time display ***
		strHTML    += '<div UNSELECTABLE="on" id="TCoDate" style="FONT-SIZE: 12px; Z-INDEX: 1; LEFT: 10px; WIDTH: 267px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; TOP: 10px; TEXT-ALIGN: left; cursor:default;">Feb. 03/2004</div>';
		strHTML    += '<div UNSELECTABLE="on" id="TCoTime" style="FONT-SIZE: 25px; Z-INDEX: 1; LEFT: 10px; WIDTH: 267px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; TOP: 30px; TEXT-ALIGN: center; cursor:default;">23:12:47:876</div>';
		strHTML    += '<div UNSELECTABLE="on" id="TCoSpeed" style="FONT-SIZE: 12px; Z-INDEX: 1; LEFT: 10px; WIDTH: 267px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; TOP: 10px; TEXT-ALIGN: right; cursor:default;">1.00x</div>';

		//*** drag controls ***
		strHTML    += '<img UNSELECTABLE="on" id="TCoDragButtonFine"     title="' + "Ajuste de hora fino" + '" style="cursor:hand; position:absolute;" src="img/timenav_sliderknob_plain.gif"  onmousedown="this.src=\'img/timenav_sliderknob_active.gif\'; oTimeControl.onMouseDown(event);" onMouseOver="" onMouseOut="" onMouseUp="this.src=\'img/timenav_sliderknob_plain.gif\';" />';
		strHTML    += '<img UNSELECTABLE="on" id="TCoDragButtonCoarse"   title="' + "Ajsute de hora grueso" + '" style="cursor:hand; position:absolute;" src="img/timenav_sliderknob_plain.gif"  onmousedown="this.src=\'img/timenav_sliderknob_active.gif\'; oTimeControl.onMouseDown(event);" onMouseOver="" onMouseOut="" onMouseUp="this.src=\'img/timenav_sliderknob_plain.gif\';" />';
		strHTML    += '<img UNSELECTABLE="on" id="TCoDragButtonPlayback" title="' + "Velocidad de reproducción" + '" style="cursor:hand; position:absolute;" src="img/timenav_sliderknob_plain.gif"  onmousedown="this.src=\'img/timenav_sliderknob_active.gif\'; oTimeControl.onMouseDown(event);" onMouseOver="" onMouseOut="" onMouseUp="this.src=\'img/timenav_sliderknob_plain.gif\';" />';
		strHTML    += '<div UNSELECTABLE="on" style="FONT-SIZE: 10px; Z-INDEX: 1; LEFT: 62px; TOP: 132px; WIDTH: 165px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; text-align:center; cursor:default;">Hora</div>';
		strHTML    += '<div UNSELECTABLE="on" style="FONT-SIZE: 10px; Z-INDEX: 1; LEFT: 4px; TOP: 132px; WIDTH: 165px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; text-align:left; cursor:default;">Atrás</div>';
		strHTML    += '<div UNSELECTABLE="on" style="FONT-SIZE: 10px; Z-INDEX: 1; LEFT: 118px; TOP: 132px; WIDTH: 165px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; text-align:right; cursor:default;">Adelante</div>';
		strHTML    += '<div UNSELECTABLE="on" style="FONT-SIZE: 10px; Z-INDEX: 1; LEFT: 4px; TOP: 161px; WIDTH: 165px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; text-align:left; cursor:default;">Lento</div>';
		strHTML    += '<div UNSELECTABLE="on" style="FONT-SIZE: 10px; Z-INDEX: 1; LEFT: 118px; TOP: 161px; WIDTH: 165px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; text-align:right; cursor:default;">Rápido</div>';
		
		//*** play controls ***
    strHTML    += '<div id="PlayForwardButton" title="' + "Reproducir adelante" + '" style="background-image:url(img/timenav_playforward_plain.gif); cursor:hand; position:absolute; top:191px; left:174px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()){if(oTimeControl.oPlaybackThread.isThreadRunning()&&(oTimeControl.m_playDirection==1)) {this.style.backgroundImage=\'url(img/timenav_playforward_active.gif)\';} else {this.style.backgroundImage=\'url(img/timenav_playforward_mouseover.gif)\';}}" onMouseOut="if(oTimeControl.getIsNavEnabled()){if(oTimeControl.oPlaybackThread.isThreadRunning()&&(oTimeControl.m_playDirection==1)) {this.style.backgroundImage=\'url(img/timenav_playforward_active.gif)\';} else {this.style.backgroundImage=\'url(img/timenav_playforward_plain.gif)\';}}" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_playforward_active.gif)\';" onclick="oTimeControl.play();"></div>';
    strHTML    += '<div title="' + "Parar" + '" style="background-image:url(img/timenav_playstop_plain.gif); cursor:hand; position:absolute; top:191px; left:128px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_playstop_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_playstop_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_playstop_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_playstop_mouseover.gif)\';" onclick="oTimeControl.stop();"></div>';
    strHTML    += '<div id="PlayReverseButton" title="' + "Reproducir invertido" + '" style="background-image:url(img/timenav_playreverse_plain.gif); cursor:hand; position:absolute; top:191px; left:82px; width:34px; height:34px;"  onMouseOver="if(oTimeControl.getIsNavEnabled()){if(oTimeControl.oPlaybackThread.isThreadRunning()&&(oTimeControl.m_playDirection==-1)) {this.style.backgroundImage=\'url(img/timenav_playreverse_active.gif)\';} else {this.style.backgroundImage=\'url(img/timenav_playreverse_mouseover.gif)\';}}" onMouseOut="if(oTimeControl.getIsNavEnabled()){if(oTimeControl.oPlaybackThread.isThreadRunning()&&(oTimeControl.m_playDirection==-1)) {this.style.backgroundImage=\'url(img/timenav_playreverse_active.gif)\';} else {this.style.backgroundImage=\'url(img/timenav_playreverse_plain.gif)\';}}" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_playreverse_active.gif)\';" onclick="oTimeControl.reversePlay();"></div>';
    strHTML    += '<div UNSELECTABLE="on" style="FONT-SIZE: 10px; Z-INDEX: 1; LEFT: 62px; TOP: 161px; WIDTH: 165px; COLOR: black; FONT-FAMILY: Tahoma; POSITION: absolute; TEXT-ALIGN: left; text-align:center; cursor:default;">Reproducción</div>';

		//*** sequence controls ***
    strHTML    += '<div title="' + "Imagen previa" + '" style="background-image:url(img/timenav_previousimage_plain.gif); cursor:hand; position:absolute; top:72px; left:104px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previousimage_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previousimage_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previousimage_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previousimage_mouseover.gif)\';" onclick="oTimeControl.onNavigate(\'onPreviousImage\');"></div>';
    strHTML    += '<div title="' + "Imagen siguiente" + '" style="background-image:url(img/timenav_nextimage_plain.gif); cursor:hand; position:absolute; top:72px; left:150px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextimage_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextimage_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextimage_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextimage_mouseover.gif)\';" onclick="oTimeControl.onNavigate(\'onNextImage\');"></div>';
    strHTML    += '<div title="' + "Secuencia previa" + '" style="background-image:url(img/timenav_previoussequense_plain.gif); cursor:hand; position:absolute; top:72px; left:58px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previoussequense_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previoussequense_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previoussequense_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_previoussequense_mouseover.gif)\';" onclick="oTimeControl.onNavigate(\'onPreviousSequence\');"></div>';
    strHTML    += '<div title="' + "Secuencia siguiente" + '" style="background-image:url(img/timenav_nextsequense_plain.gif); cursor:hand; position:absolute; top:72px; left:196px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextsequense_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextsequense_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextsequense_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_nextsequense_mouseover.gif)\';" onclick="oTimeControl.onNavigate(\'onNextSequence\');"></div>';
    strHTML    += '<div title="' + "Primera imagen" + '" style="background-image:url(img/timenav_firstimage_plain.gif); cursor:hand; position:absolute; top:72px; left:12px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_firstimage_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_firstimage_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_firstimage_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_firstimage_mouseover.gif)\';" onclick="oTimeControl.onNavigate(\'onFirstImage\');"></div>';
    strHTML    += '<div title="' + "Última imagen" + '" style="background-image:url(img/timenav_latestimage_plain.gif); cursor:hand; position:absolute; top:72px; left:242px; width:34px; height:34px;" onMouseOver="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_latestimage_mouseover.gif)\';" onMouseOut="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_latestimage_plain.gif)\';" onMouseDown="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_latestimage_active.gif)\';" onMouseUp="if(oTimeControl.getIsNavEnabled()) this.style.backgroundImage=\'url(img/timenav_latestimage_mouseover.gif)\';" onclick="oTimeControl.onNavigate(\'onLatestImage\');"></div>';

	strHTML    += '</div>';
	return strHTML;
}
 
//-->event hooks
TimeControl.prototype.onChangeTime = function(oDate) {
	alert("onChangeTime is pure virtual - please override");
	//oImageLoader1.loadFromDate(this.m_time);
}
TimeControl.prototype.onFirstImage = function() {
	alert("onFirstImage is pure virtual - please override");
}
TimeControl.prototype.onPreviousSequence = function() {
	alert("onPreviousSequence is pure virtual - please override");
}
TimeControl.prototype.onPreviousImage = function() {
	alert("onPreviousSequence is pure virtual - please override");
}
TimeControl.prototype.onNextImage = function() {
	alert("onNextImage is pure virtual - please override");
}
TimeControl.prototype.onNextSequence = function() {
	alert("onNextsequence is pure virtual - please override");
}
TimeControl.prototype.onLatestImage = function() {
	alert("onLatestImage is pure virtual - please override");
}
TimeControl.prototype.onPlaybackStart = function() {
	alert("onPlaybackStart is pure virtual - please override");
}
TimeControl.prototype.onPlaybackStop  = function() {
	alert("onPlaybackStop is pure virtual - please override");
}
TimeControl.prototype.onKnobDragStart = function() {
	alert("onKnobDragStart is pure virtual - please override");
}
TimeControl.prototype.onKnobDragStop  = function() {
	alert("onKnobDragStop is pure virtual - please override");
}
//*** END PUBLIC INTERFACE ***


//*** setter/getter methods ***
TimeControl.prototype.setDragCoarse = function(bEnableDrag) {
	this.m_isDraggedCoarse=bEnableDrag;
}
TimeControl.prototype.setDragFine = function(bEnableDrag) {
	this.m_isDraggedFine=bEnableDrag;
}
TimeControl.prototype.setDragPlayback = function(bEnableDrag) {
	this.m_isDraggedPlayback=bEnableDrag;
}
TimeControl.prototype.getIsNavEnabled = function() {
	return this.m_isNavEnabled;
}
TimeControl.prototype.setIsNavEnabled = function(bEnableNav) {
	this.m_isNavEnabled=bEnableNav;
}
TimeControl.prototype.getIsPlaybackEnabled = function(bEnableNav) {
	return this.m_isPlaybackEnabled;
}
TimeControl.prototype.setIsPlaybackEnabled = function(bEnableNav) {
	this.m_isPlaybackEnabled=bEnableNav;
}
//*** sequence controls ***
TimeControl.prototype.onNavigate = function(strNavEvent) {
	if(this.getIsPlaybackEnabled()) this.stop();		//stop playback
	
	if(this.getIsNavEnabled()) {
		switch(strNavEvent) {
			case 'onFirstImage'		: this.onFirstImage();break;
			case 'onPreviousSequence'	: this.onPreviousSequence();break;
			case 'onPreviousImage'		: this.onPreviousImage();break;
			case 'onNextImage'		: this.onNextImage();break;
			case 'onNextSequence'		: this.onNextSequence();break;
			case 'onLatestImage'		: this.onLatestImage();break;
		}
	}
}
//*** play controls ***
TimeControl.prototype.play = function() {
	if(!this.getIsPlaybackEnabled()) {
		this.setIsPlaybackEnabled(true);
		this.onPlaybackStart();
	}

  document.getElementById("PlayReverseButton").style.backgroundImage = "url(img/timenav_playreverse_plain.gif)";
  document.getElementById("PlayForwardButton").style.backgroundImage = "url(img/timenav_playforward_active.gif)";

	this.m_playDirection=1;
	this.oPlaybackThread.stop();
	this.oPlaybackThread.setPeriode(this.m_beaconPeriode);

	var oDate = new Date();
	this.m_loopBackTime = oDate.getTime();
	
	this.oPlaybackThread.start();
}
TimeControl.prototype.stop = function() {
	if(this.getIsPlaybackEnabled()) {
		this.setIsPlaybackEnabled(false);
		this.onPlaybackStop();
    this.updateDisplay();
	}
  document.getElementById("PlayForwardButton").style.backgroundImage = "url(img/timenav_playforward_plain.gif)";
  document.getElementById("PlayReverseButton").style.backgroundImage = "url(img/timenav_playreverse_plain.gif)";
	this.oPlaybackThread.stop();
}
TimeControl.prototype.reversePlay = function() {
	if(!this.getIsPlaybackEnabled()) {
		this.setIsPlaybackEnabled(true);
		this.onPlaybackStart();
	}

  document.getElementById("PlayForwardButton").style.backgroundImage = "url(img/timenav_playforward_plain.gif)";
  document.getElementById("PlayReverseButton").style.backgroundImage = "url(img/timenav_playreverse_active.gif)";

	this.m_playDirection=-1;
	this.oPlaybackThread.stop();
	this.oPlaybackThread.setPeriode(this.m_beaconPeriode);

	var oDate = new Date();
	this.m_loopBackTime = oDate.getTime();

	this.oPlaybackThread.start();
}
TimeControl.prototype.pulse = function() {
	var oTime = new Date();
	var t = oTime.getTime();

	var misPredictionFactor = (t - this.m_loopBackTime)/this.m_beaconPeriode;
	this.m_loopBackTime = t;

	this.adjustTime(this.m_playDirection*Math.round(this.m_advanceTime*misPredictionFactor));
}

//*** methods pertaining to time adjustment ***
TimeControl.prototype.timePanning = function() {
	//only one thread here at a time

	//which knob is being handled?
	if(this.m_isDraggedCoarse) {
		var x = parseInt(TCoDragButtonCoarse.style.left,10);	//radial distance
		var dx = x-this.m_initCoarseCoors.x;					//from center.
		var milliSecPan = this.speedTransCoarse(dx);
		this.adjustTime(milliSecPan);
	} 
  else if(this.m_isDraggedFine) {
		var x = parseInt(document.all["TCoDragButtonFine"].style.left,10);	//radial distance
		var dx = x-this.m_initFineCoors.x;					//from center.
		var milliSecPan = this.speedTransFine(dx);
		this.adjustTime(milliSecPan);
	}
}

TimeControl.prototype.speedTransFine = function(dx) {
	//implements a knob slagg around the middle of the slide
	if( (dx >= 0) && (dx < this.m_fineSlaggRadius)) {
		return 0;
	}
	else if( (dx <= 0) && (-dx < this.m_fineSlaggRadius)) {
		return 0;
	} 
	//calc speed factor
	if(dx >= 0) return parseInt(this.m_minFineSpeedV*Math.exp(this.m_fineSpeedSlope*dx),10);
	else return -1*parseInt(this.m_minFineSpeedV*Math.exp(-this.m_fineSpeedSlope*dx),10);
}
TimeControl.prototype.speedTransCoarse = function(dx) {
	//implements a knob slagg around the middle of the slide
	if( (dx >= 0) && (dx < this.m_coarseSlaggRadius)) {
		return 0;
	}
	else if( (dx <= 0) && (-dx < this.m_coarseSlaggRadius)) {
		return 0;
	} 

	//calc speed factor
	if(dx >= 0) return parseInt(this.m_minCoarseSpeedV*Math.exp(this.m_coarseSpeedSlope*dx),10);
	else return -1*parseInt(this.m_minCoarseSpeedV*Math.exp(-this.m_coarseSpeedSlope*dx),10);
}
TimeControl.prototype.speedTransPlayback = function(dx) {
	var mx;

	//implements a knob slagg around the middle of the slide
	if( (dx >= 0) && (dx < this.m_playbackSlaggRadius)) {
		return 1;
	}
	else if( (dx <= 0) && (-dx < this.m_playbackSlaggRadius)) {
		return 1;
	} 

	//calc speed factor
	//alert(dx);
	if(dx >= 0) {
  	mx = this.m_dimension.width-this.m_padding.right-this.m_initPlaybackCoors.x-Math.round(this.m_cPlaybackKnobWidth/2);
		mx = 1+this.m_maxPlaybackFactor*((dx)/mx);
    mx = Math.floor(mx);
	}
	else {
		mx = -(this.m_initPlaybackCoors.x-this.m_padding.left+Math.round(this.m_cPlaybackKnobWidth/2));
		mx = 1-((dx)/mx);	//this.m_maxPlaybackFactor*
		//alert(mx);
	}
	return mx;
}
TimeControl.prototype.adjustTime = function(deltaTimeInMilliSecs) {
	this.m_pulseCounter++;
	
	this.m_time			= new Date((this.m_time).getTime()+deltaTimeInMilliSecs);
	
	var years = this.m_years;
	var months = this.m_months;
	var days = this.m_days;
	
	this.m_years		= this.m_time.getFullYear();
	this.m_months		= this.m_time.getMonth()+1;
	this.m_days			= this.m_time.getDate();

	//check if date has changed
	if( (this.m_years != years) || (this.m_months != months) || (this.m_days != days))	(document.all["TCoDate"]).innerText =this.m_time.toLocaleDateString();

	this.m_hours		= this.m_time.getHours();
	this.m_mins			= this.m_time.getMinutes();
	this.m_secs			= this.m_time.getSeconds();
	this.m_milliSecs	= this.m_time.getMilliseconds();
	
	var hours=this.m_hours;
	var mins=this.m_mins;
	var secs=this.m_secs;
	var milliSecs=this.m_milliSecs;
	
	if(hours<10) hours="0"+this.m_hours;
	if(mins<10)  mins="0"+this.m_mins;
	if(secs<10)  secs="0"+this.m_secs;

	if(milliSecs<10) milliSecs="00"+milliSecs; 
	else if(milliSecs<100)  milliSecs="0"+milliSecs;
	
	if(this.m_pulseCounter > this.m_cUpdateDisplayThreshold) {
		this.m_pulseCounter = 0;
		(document.all["TCoTime"]).innerText=hours+":"+mins+":"+secs+":"+milliSecs;
	}
	this.onChangeTime(this.m_time);
}
TimeControl.prototype.updateDisplay = function() {
	this.m_pulseCounter=this.m_cUpdateDisplayThreshold+1;
	this.adjustTime(0);
}
//*** methods pertaining to knob movement ***
TimeControl.prototype.centerFineKnob = function() {
	var x = parseInt(document.all["TCoDragButtonFine"].style.left,10);
	var dx = x-this.m_initFineCoors.x;						//calc. the new
	(this.m_fineVel).vx+=-this.cFineSpringConst*dx;			//velocity vector.
	(this.m_fineVel).vx *= this.cFineEnergyLossFactor;		//damping factor for reducing the energy

	if(Math.round((this.m_fineVel).vx) ==0  && Math.abs(dx)<=5) {
		(this.oFineThread).stop();
		document.all["TCoDragButtonFine"].style.left=this.m_initFineCoors.x;
	} 
  else 
    document.all["TCoDragButtonFine"].style.left=x+Math.floor((this.m_fineVel).vx)+"px";
	
}
TimeControl.prototype.centerCoarseKnob = function() {
	var x = parseInt(TCoDragButtonCoarse.style.left,10);
	var dx = x-this.m_initCoarseCoors.x;						//calc. the new
	(this.m_coarseVel).vx+=-this.cCoarseSpringConst*dx;			//velocity vector.
	(this.m_coarseVel).vx *= this.cCoarseEnergyLossFactor;		//damping factor for reducing the energy

	if(Math.round((this.m_coarseVel).vx) ==0  && Math.abs(dx)<=5) {
		(this.oCoarseThread).stop();
		TCoDragButtonCoarse.style.left=this.m_initCoarseCoors.x;
	} else TCoDragButtonCoarse.style.left=x+Math.floor((this.m_coarseVel).vx)+"px";
	
}
//*** EVENT LISTENERS/TRIGGERS ***
TimeControl.prototype.onMouseMove = function() {
	if(this.m_isDraggedCoarse) {
		this.onCoarseMove();
	}
	else if(this.m_isDraggedFine) {
		this.onFineMove();
	}
	else if(this.m_isDraggedPlayback) {
		this.onPlaybackMove();
	}
}
TimeControl.prototype.onFineMove = function() {
    var knob = document.all["TCoDragButtonFine"];
		var x = parseInt(window.event.clientX,10)-getPageOffsetLeft(document.all["TCoHTMLtimeControl"])-Math.round(this.m_cFineKnobWidth/2);
		if(x < this.m_padding.left-Math.round(this.m_cFineKnobWidth/2) ) {
			x = this.m_padding.left-Math.round(this.m_cFineKnobWidth/2);
		}
		else if( x > this.m_dimension.width-this.m_padding.right-Math.round(this.m_cFineKnobWidth/2)) {
			x = this.m_dimension.width-this.m_padding.right-Math.round(this.m_cFineKnobWidth/2);
		}
		knob.style.left = x; 
}
TimeControl.prototype.onCoarseMove = function() {
    var knob = document.all["TCoDragButtonCoarse"];
		var x = parseInt(window.event.clientX,10)-getPageOffsetLeft(document.all["TCoHTMLtimeControl"])-Math.round(this.m_cCoarseKnobWidth/2);
		if(x < this.m_padding.left-Math.round(this.m_cCoarseKnobWidth/2) ) {
			x = this.m_padding.left-Math.round(this.m_cCoarseKnobWidth/2);
		}
		else if( x > this.m_dimension.width-this.m_padding.right-Math.round(this.m_cCoarseKnobWidth/2)) {
			x = this.m_dimension.width-this.m_padding.right-Math.round(this.m_cCoarseKnobWidth/2);
		}
		knob.style.left = x; 
}
TimeControl.prototype.onPlaybackMove = function() {
    var knob = document.all["TCoDragButtonPlayback"];
		var x = parseInt(window.event.clientX,10)-getPageOffsetLeft(document.all["TCoHTMLtimeControl"])-Math.round(this.m_cPlaybackKnobWidth/2);
		if(x < this.m_padding.left-Math.round(this.m_cPlaybackKnobWidth/2) ) {
			x = this.m_padding.left-Math.round(this.m_cPlaybackKnobWidth/2);
		}
		else if( x > this.m_dimension.width-this.m_padding.right-Math.round(this.m_cPlaybackKnobWidth/2)) {
			x = this.m_dimension.width-this.m_padding.right-Math.round(this.m_cPlaybackKnobWidth/2);
		}
		this.m_advanceTime = Math.round(this.speedTransPlayback(x-this.m_initPlaybackCoors.x)*this.m_beaconPeriode);
		knob.style.left = x; 
		
		//update speed indicator
		var speedRatio = parseInt(100*this.m_advanceTime/this.m_beaconPeriode)/100;	//2 decimals
		var dispText;

		//if(speedRatio == 1) dispText = " RT ";
		if(speedRatio == 0) dispText = "pausa";
		else {
			dispText = parseInt(speedRatio,10);
			var dec1 = parseInt((speedRatio*10),10) % 10;
			var dec2 = parseInt((speedRatio*100),10) % 10;
			
			if( dec1==0 && dec2==0) dispText+=".00x";
			else if( dec1!=0 && dec2==0) dispText+= ("."+dec1+"0x");
			else dispText+= ("."+dec1+dec2+"x");
		}
		
		document.all["TCoSpeed"].innerText=dispText;


}
TimeControl.prototype.onMouseUp = function() {
	if(this.m_isDraggedFine) {
		this.setDragFine(false);
		this.onKnobDragStop();
		
		if(this.oFineThread.isRunning) this.oFineThread.stop();		//if thread is running then
		this.oFineThread.setCallbackMethodName("centerFineKnob");	//stop it, config. for centering knob,
		this.oFineThread.start();									//and start it again
		this.updateDisplay();
	}
	else if(this.m_isDraggedCoarse) {
		this.setDragCoarse(false);
		this.onKnobDragStop();

		if(this.oCoarseThread.isRunning) this.oCoarseThread.stop();		//if thread is running then
		this.oCoarseThread.setCallbackMethodName("centerCoarseKnob");	//stop it, config. for centering knob,
		this.oCoarseThread.start();										//and start it again
		this.updateDisplay();
	}
	else if(this.m_isDraggedPlayback) {
		this.setDragPlayback(false);
		//this.updateDisplay();
	}
}
TimeControl.prototype.onMouseDown = function() {
	var myEvent = window.event;
	if(myEvent.srcElement.id=="TCoDragButtonFine") {
		if(this.oFineThread.isRunning) {
      this.oFineThread.stop();		//if thread is running then
    }
		this.oFineThread.setCallbackMethodName("timePanning");		//stop it, config. for time panning,
		this.oFineThread.start();									//and start it again
		
		this.setDragFine(true);
		this.onKnobDragStart();
	}
	else if(myEvent.srcElement.id=="TCoDragButtonCoarse") {
			if(this.oCoarseThread.isRunning) this.oCoarseThread.stop();		//if thread is running then
			this.oCoarseThread.setCallbackMethodName("timePanning");		//stop it, config. for time panning,
			this.oCoarseThread.start();									//and start it again

			this.setDragCoarse(true);
			this.onKnobDragStart();
		}
		else if(myEvent.srcElement.id=="TCoDragButtonPlayback") {
			this.setDragPlayback(true);
		}
}