/****************************************************************************************

                     BLOCKZOOM.JS

This code and algorithms are 
Copyright (C) 2009 DragonLord Enterprises, Inc. dba Sequoia Consulting.  All rights reserved.
Reuse of code or derivative works prohibited without license.


INSTRUCTIONS


DESCRIPTION OF SYSTEM


DESIGN

-First pass:  Turn things relative, change z-stacking, then move them and grow them.
    Main consideration:  Can't change fill order of current page, while you're zooming the overlay.

--Second pass.  Can't move them and grow them while relative, because growing a relative 
  enlarges the previous place.  Lose.  Have to clone, turn original invisible, then grow clone.
  Will want to manipulate clone and stuff it, anyway.



NOTES
*  System is quietly multi-threaded (init vs. animation).  Don't hammer yourself.
*  .style.top vs. .style.clientTop:  
*  IF DIV IS DEFINED USING LAYOUTGRID (CSS), THEN ITS WIDTH AND HEIGHT DO NOT ANIMATE--OVERRIDDEN.  !!!!!
*  0.20 looks wimpy.  

HISTORY
Apr 18 '08  IE requires local variables to explicitly have a var in front.
            Also can't say Obj.class = "House".
             IE does not honor setattribute = "STYLE", have to do things the long way, with individual .style.foo slots.
Apr 20 '08	Turns out you can't read thisblock.style.position.  Style is typically a COMPUTED
			attribute that does not get stored natively if it is not set.  Proper syntax is:
			window.getComputedStyle( thisblock, null).getPropertyValue("position");
			this one took four hours.
Apr 21 '08  Can't ready this.style.width either.
			It comes up as NaN.
			This nulls out the parseInt, instead of setting to 0,
			which takes down the proportional dialer system.
			This and associated bugs took 5 hours to track down.


BUGS
*  spelled getElementById incorrectly.
*  using block.width, not block.style.width.  Also it's block.style.position.  
*  Use parseInt() and  +"px" for best luck.
*  undefined is a keyword and cannot be a string.
*  "hidden", on the other hand, is a string value.

TO DO:

*****************************************************************************************/
/////////////////////////SYSTEM PARAMETERS////////////////////////////////

//var slots_per_Stock_obj = 8;

//var repaint = 0;

var d;  //will be used to read Date Time.

// Find width and height of entire viewport:
var viewporttop = 0;
var viewportleft = 0;
 var viewportwidth;
 var viewportheight;
 // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
 if (typeof( window.innerWidth ) != undefined)   //magic for testing properties which might not be extant.
 {
      viewportwidth = window.innerWidth;
      viewportheight = window.innerHeight;
 }
// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
 else if (typeof( document.documentElement )!= undefined
     && typeof( document.documentElement.clientWidth )!=
     'undefined' && document.documentElement.clientWidth != 0)
 {
       viewportwidth = document.documentElement.clientWidth;
       viewportheight = document.documentElement.clientHeight;
 }
  else if (typeof( document.body ) != undefined
  	&& document.body != null
     && typeof( document.body.clientWidth ) !=
     undefined && document.body.clientWidth != 0)
 {
       viewportwidth = document.body.clientWidth;
       viewportheight = document.body.clientHeight;
 }
 // o
 // older versions of IE
 else
 {
       viewportwidth = document.getElementsByTagName('body')[0].clientWidth;    //iW = document.body.clientWidth; 
       viewportheight = document.getElementsByTagName('body')[0].clientHeight;
 }


var obj_absolute_top = 0;
var obj_absolute_left = 0;
function getPosition(obj)
{
    var topValue= 0,leftValue= 0;
    while(obj){
    
//    alert( obj + ": ( " + obj.offsetLeft +" , " + obj.offsetTop  +  ")" );
    
    
	leftValue+= parseInt(obj.offsetLeft);  //oops.
	topValue+= parseInt(obj.offsetTop);  //NOTE OFFSETLEFT AND OFFSETTOP ARE "READ ONLY" BROWSER HACKS, IE AND FF.
	obj= obj.offsetParent;
    }
//    finalvalue = leftValue + "," + topValue;
//    return finalvalue;
	obj_absolute_top  =  topValue;
	obj_absolute_left = leftValue;
}


var startblocktop;
var startblockleft;
var startblockwidth;
var startblockheight;
var CurrentAnimationObj;
function Setup_Fire_ExpandThisBlockToFullWindow_Animation_a( thisblockIDname, go_to )
// for <a href="newlink" id="tag" onclick="  "
{
	var thisblock  = document.getElementById( thisblockIDname );
//	var currentpos = thisblock.style.position;   //r elative  f ixed  s tatic  a bsolute  NG, comes out NULL.
//	var currentpos = thisblock.style.getPropertyValue("position") + "!";
//	var currentpos = window.getComputedStyle( thisblock, "position");
	var currentpos;
	if( typeof( thisblock.style.position) != undefined && thisblock.style.position != null )
		currentpos = thisblock.style.position;
	else
		currentpos = window.getComputedStyle( thisblock, null).getPropertyValue("position");
	//alert( thisblock + ": " + currentpos + "=" + thisblock.style.position + " /= " + thisblock.position  );
	currentpos = currentpos.charAt(0);   //r elative  f ixed  s tatic  a bsolute
	//alert( currentpos );
		
	//alert( "Using" + thisblock );
	//thisblock.style.display = "none";
	//thisblock.style.width   =  300;
//	//thisblock.style.height = 300;
	//thisblock.style.position = "relative";
	//thisblock.style.clientTop = 300;
	//thisblock.style.clientLeft = 300;
	//thisblock.style.top = 30;
	//thisblock.style.left = 30;
	
	// Get size of whole window
	//viewportwidth;
	//viewportheight;
	
	//Save in global target end variables
	//already there, thanks.
	
	//Get my size, and save in global start variables
	getPosition(thisblock );
	var startblocktop = obj_absolute_top; //parseInt(thisblock.style.clientTop);
	var startblockleft = obj_absolute_left; // parseInt(thisblock.style.clientLeft);
	var startblockwidth;  //VERY NECESSARY ADD 0 ONTO END TO KILL NaN-- NO GOOD DOESN'T WORK, ALREADY POISONED.
	var startblockheight;
	
//	if( typeof( thisblock.style.width) != undefined && thisblock.style.width != null )
//	{	startblockwidth = parseInt(thisblock.style.width);
//	alert("ist' there:" + thisblock.style.width);
//	}
//	else
	{
		startblockwidth = parseInt( window.getComputedStyle( thisblock, null).getPropertyValue("width"));	
//		alert ("Not there pluck." + startblockwidth);
	}
		
//	if( typeof( thisblock.style.height) != undefined && thisblock.style.height != null )
//		startblockheight = parseInt(thisblock.style.height);
//	else
		startblockheight = parseInt(  window.getComputedStyle( thisblock, null).getPropertyValue("height"));			

//alert( currentpos + ": w,h= " + " ( " + startblockwidth + " , " + startblockheight + " )" );
	


	// NEW CONTENTS:
	var newcontents = go_to; //thisblock.href;
//	alert( "Using New Contents " + newcontents );
	var newblock = newDiv( newcontents,  startblocktop, startblockleft, startblockwidth, startblockheight );  
	
	thisblock = newblock;

	//  COPY THISBLOCK INTO NEW BLOCK.  SHALLOW COPY ATTACHMENTS.
	
	//  MAKE OLD BLOCK INVISIBLE.
	
	//  ATTACH NEW BLOCK TO TOP LEVEL WINDOW.  MAKE IT ABSOLUTE
	
	//  FILL IN X, Y POSITIONS.

	//alert( currentpos + ": " + " ( " + startblocktop + " , " + startblockleft + " )" );
	
	//Stuff animation parameters
	
	var blockObj = new ExpandingBlockAnimationObject ( startblocktop, startblockleft, startblockwidth, startblockheight,
                                         viewporttop, viewportleft, viewportwidth, viewportheight,
                                         currentpos,
                                         thisblock );
                                         
	// jack it up above all others.
	thisblock.zIndex = 2;
	//Fire animation object
	
	CurrentAnimationObj = blockObj;
	
	CurrentAnimationObj.animation = setInterval ( "Animate_Current_Animation_Obj()", 50 );   //Note:  "this" will refer to WINDOW not OBJECT.
	//Basically MUST be a global function.  There are hacks to circumvent, having to do with hash-table the obj then lookup.

//	blockObj.Animate();
}

function ExpandingBlockAnimationObject ( start_top, start_left, start_width, start_height,
                                         end_top, end_left, end_width, end_height,
                                         current_pos,
                                         this_block )
{
	//SLOTS.  All these are PUBLIC and INDIVIDUAL.
	this.starttop 	= start_top;
	this.startleft 	= start_left;
	this.startwidth	= start_width;
	this.startheight = start_height;
	
	this.endtop		= end_top;
	this.endleft	= end_left;
	this.endwidth	= end_width;
	this.endheight	= end_height;
	
	this.currentpos	= current_pos;
	this.thisblock	= this_block;
	
	d = new Date();
	this.StartTime	=	d.getTime();  //Time in milliseconds.  No GC in JavaScript,just leave it lying there.
	
	//Stuff animation parameters	
	
	
  //METHODS.  Undeclared functors defined in-line; otherwise use funcname w/o ().
  //  this.barefunc = function(){ }  //???	
  //  this.method    = outside_function;  //NO ().
  //  Method definition functions may use this.slot variables without declaring them!
  
  this.Animate = BlockExpand_AnimationFrame;
  this.SetSize = Set_Size;

}


function BlockExpand_AnimationFrame ()
{
	var HeightEase1 = 0.5;    //0.0 to 0.49    starting ease proportional distance, default 0.20
	var HeightEase2 = 0.5;   //0.0 to 0.49,   ending ease proportional distance, default 0.20
	var EaseTime1 = 1000;	//starting ease duration.  milliseconds.  Should be less than 1/2 of T.  default 0.5 CAN'T BE 0.0!!!!
	var EaseTime2 = 1000;	//ending ease duration.    milliseconds.  Should be less than 1/2 of T.  default 0.5.
	var T = 2000;   			//Total predefined duration for animation, milliseconds, default 4.0 seconds
	//StartTime;			//capture this for start
	d = new Date();
	var CurrentTime = d.getTime();		//ongoing current animation time.
	var t = CurrentTime - this.StartTime;    //JavaScript IS Case-Sensitive (confirmed).
	
	var x;     //output variable for animation proportion.  Between 0.0 and 1.0.
	
	
	//Third case, ending ease.
	//This MUST be checked first, in case T got whacked too small!
	if( t >= ( T - EaseTime2 ) )
	{
		x =  1  -  ( (HeightEase2 / ( EaseTime2 * EaseTime2 ))  *  ( T - t ) * (T - t) )  ;
	}
	else if (  t <  EaseTime1 )
	{
		x = (  HeightEase1  /  ( EaseTime1 * EaseTime1 ) )   *   t  *  t  ;
	}
	else
	{
		x  =  HeightEase1  +  ( t - EaseTime1) * ( 1.0 - HeightEase1 - HeightEase2 ) /  ( T  - EaseTime1  -  EaseTime2 ) ;
	}
	
	
	
	//x = t / T;
	//if (x > 1) x = 1;
	
	//x = 0.5;
	
	
	this.SetSize( x, this.currentpos );
	
	if( t >= T )
	{
		clearInterval( CurrentAnimationObj.animation );
		CurrentAnimationObj.thisblock.zIndex = 1;  //or 0.
		CurrentAnimationObj.thisblock.style.border = null;
		CurrentAnimationObj = null;
	}
		
}


function Set_Size( x, currentpos )
{
	
//	alert( "SetSize... " + currentpos + ":x" + x + " (" + this.starttop + "," + this.startleft + ") ==> (" + this.endtop + "," + this.endleft + ")"  );
	
//	if( currentpos == 'a' )
	{
	//ONLY WORKS ON / ASSUMES ABSOLUTE IS TIED TO TOP LEVEL WINDOW.  
	//NESTEDS WILL PROBABLY REQUIRE TURNING CURRENT INVISIBLE, PLUS MAKING A CLONE.
		this.thisblock.style.position = "absolute";
		//starttop KEEPS absolute  starting at 0.
		this.thisblock.style.top  = this.starttop   +   x * ( this.endtop   -  this.starttop );
		this.thisblock.style.left = this.startleft  +   x * ( this.endleft  -  this.startleft );
	}
/*
	else  //assuming STATIS
	{
		this.thisblock.style.position = "relative"; 
		
		//starttop starts out absolute but then turns RELATIVE starting at 0.
		this.thisblock.style.top  =   -  x * ( this.endtop   -  this.starttop );
		this.thisblock.style.left =   -  x * ( this.endleft  -  this.startleft );	
	}
*/	
	//width and height are traditional dials.
	this.thisblock.style.width   = this.startwidth  +  x * ( this.endwidth    -  this.startwidth ) + "px";
	this.thisblock.style.height  = this.startheight +  x * ( this.endheight   -  this.startheight ) + "px";

//	alert( "SetSize... w,h = (" + this.thisblock.style.width + ", " + this.thisblock.style.height + ")"  );

	
}


function Animate_Current_Animation_Obj()
{
	if(CurrentAnimationObj)
	{
		CurrentAnimationObj.Animate();
	}
}


function newDiv( contents, mytop, myleft, mywidth, myheight )
{
	var divTag = document.createElement("div");
	//divTag.id = "div1";
	//divTag.setAttribute("align","center");
	//divTag.style.margin = "0px auto";
	//divTag.className ="dynamicDiv";  //may be used with CSS to add more attributes.
	//divTag.innerHTML = "This HTML Div tag is created using Javascript DOM dynamically.";

//	divTag.innerHTML = contents;
	divTag.style.top 	= mytop;
	divTag.style.left	= myleft;
	divTag.style.width	= mywidth + "px";
	divTag.style.height	= myheight + "px";
	
	divTag.style.backgroundColor = "#FFFFFF";

//	alert( " " + divTag.style.width + "," + divTag.style.height );
	
	divTag.style.border = "green solid";
	
	divTag.style.overflow = "hidden";   //Magic for clipping on right and bottom.
//	divTag.overflow = "hidden";   //Magic for clipping on right and bottom.
	
	divTag.innerHTML = contents;	

	divTag.style.zIndex = 2;


	document.body.appendChild(divTag);
	divTag.style.position = "absolute";
	
	return(divTag);
}






var isIE = 0;

/////////////////////////////////////////////////////////////////////
function getInternetExplorerVersion()
// Returns the version of Internet Explorer or a 0  (was -1)
// (indicating the use of another browser).
{
  var rv = 0; //-1; // Return value assumes failure.  WAS -1
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}
//function checkVersion()
//{
//  var msg = "You're not using Internet Explorer.";
//  var ver = getInternetExplorerVersion();
//
//  if ( ver > -1 )



function init()
//Initializes all of the objects, and the entire system.
//Called automatically upon loading (see last line of this file).
{
	isIE = getInternetExplorerVersion();

};















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

	     




function handlecommands(results)
//MAIN CLIENT INPUT SOCKET TO GLUE, FROM SERVER
//translation layer
{
	var commandstring = results;  //"fix".  Why is this two steps?
	var Commands = commandstring.split("|");  //was ",".
		//length is array SLOT not METHOD:		
	var commandcount = Commands.length / slots_per_Stock_obj;
	var stock;
	repaint = 1;
	
	var i;
	for(i=0; i<commandcount; i++)
	{
		var command   = Commands[i*slots_per_Stock_obj    ];
		var stockname = Commands[i*slots_per_Stock_obj + 1] - 0;
		var bid       = Commands[i*slots_per_Stock_obj + 2] - 0;
		var ask       = Commands[i*slots_per_Stock_obj + 3] - 0;
		var grade     = Commands[i*slots_per_Stock_obj + 4];
		var score     = Commands[i*slots_per_Stock_obj + 5] - 0;
		var longname  = Commands[i*slots_per_Stock_obj + 6];
		var ornament  = Commands[i*slots_per_Stock_obj + 7] - 0;		
		
		switch( command )
		{
			case 'S':
				stock = new Stock( command, stockname, bid, ask, grade,score, longname, ornament);
				Stocks.Push( stock );
				Sells.Push( stock );
			break;
			
			case 'H':
				stock = new Stock( command, stockname, bid, ask, grade,score, longname, ornament);
				Stocks.Push( stock );
				Holds.Push( stock );			
			break;
			
			case 'B':
				stock = new Stock( command, stockname, bid, ask, grade,score, longname, ornament);
				Stocks.Push( stock );
				Buys.Push( stock );				
			break;
			
			default:
			
			break;
		}
		//Mostly "NO DIRECT COMMANDS HERE, ONLY ALTER *STATE* OF LIVE ADAPTING SYSTEM."
	}
	repaint = 1;	
}


function CleanUp()
//This function is called after all the trucks have finished moving.
//It resets the color of the pushbutton, and clears out the Agenda listing.
{
//	document.getElementById("doit_button").style.background = "#EEEEFF";
//	Clear_Agenda();
}


function handle_strategy()
// This top-level function handles semantic processing of what's going on.
// CALLED EVERY HEARTBEAT, 1st FUNCTION.
{	var i;
	var stilltodo = 0;
	

}


function simulate()
//  This function handles low-level movement animation and display.
//  Animate at a one-pixel rate.
// CALLED EVERY HEARTBEAT, 2nd FUNCTION.
{	var i;
	
}





function drawstuff()
// Handles drawing the world.
{	var i;
/*	if(repaint)
	{

	}
	repaint = 0;
	*/
}


/*
function heartbeat()
// This function handles the basics of animation.  on the CLIENT SIDE.
{
	handle_strategy();
//	simulate();
	drawstuff();
}
*/



//init();

//var timerID = setTimeout ( "setToBlack()", 2000 );
// clearTimeout( timerID );    clearInterval( timerID );
//setInterval ( "heartbeat()", 10 );  //Time in msec.  LOCAL CLIENT SIDE.
