//glimmer.js
//Author: Joshua Birk
//current modDate: Aug,26,1999
//Version: 2.0.1

//Javascript library for cross-browser dHTML functions.

//this library and its respective components are open for any use
//in its unaltered state.  Altered, this library and any component
//or module of it are commentware.  If you change it, comment it in
//the source before release.  This includes previously existing comments.

//if you have made a change that may benefit everyone, please email
//inkless@inkless.com with a synopsis.


//Some of these core functions are modified versions of dynApi so:
/**************************************************
This JavaScript code uses techniques found at
The Dynamic Duo - http://www.dansteinman.com/dynduo/
**************************************************/


//this is the core library, responsible for base functions and constructors.
//other libraries are mods to this one and this one is required.


//set Global Variables -- most of these are for the codette-passing
//others to simplify syntax
//codette has been recently simplified
layer_refer = "";
browser_version = "";
layer_name = new Array();
layer_obj = new Array();
end = "";
pause = "pause";
jump = "jump";
var pi = Math.PI;

current_draggable = "";

modules_names = new Array();
modules_values = new Array();

pager1_values = new Array();
pager1_values[0] = "nothing";
pager2_values = new Array();
pager2_values[0] = "nothing";
pager3_values = new Array();
pager3_values[0] = "nothing";

addMod("nothing",layer_report);

//these first functions are executive, they do control operations
//across the layer specific functions

//returns browser version (not type)
function checkVer() {
browser = navigator.appName;
    browser_version = parseInt(navigator.appVersion);
    return browser_version;
}

//do nothing - sometimes useful
function voidOut() {
	}

//scan through all tags for ids and fill out arrays
//for layer names and object names
function readAll() {
  if (document.getElementById) {
		j = 0;
		d = document.getElementsByTagName("div");
		for ( zz = 0; zz < d.length; zz++ )
		{    
		if (d[zz].id != "") {
			layer_name[j] = "layer_"+d[zz].id;
			layer_obj[j] = d[zz].id;
			j = j+1;
			}
		}
	}
	if (document.all) {
		j = 0;
		for ( zz = 0; zz < document.all.length; zz++ )
		{    
		if (document.all(zz).id != "") {
			layer_name[j] = "layer_"+document.all(zz).id;
			layer_obj[j] = document.all(zz).id;
			j = j+1;
			}
		}
	}
	if (document.layers) {
		j = 0;
		for ( zz = 0; zz < document.layers.length; zz++ )
		{    
		if (document.layers[zz].name != "") {
			layer_name[j] = "layer_"+document.layers[zz].name;
			layer_obj[j] = document.layers[zz].name;
			j = j+1;
			}
		}
	}
}

//initialize all layer objects based on tags with ids.
function initAll() {
	var q;
	readAll();
	for ( q = 0; q < layer_obj.length; q++ ){
		eval(layer_name[q] +"= new layer('"+layer_obj[q]+"'\)");
		}
	}	

//generate Arrays of new functions based on mods
function addMod(name,value) {
	var l = modules_names.length;
	modules_names[l]=name;
	modules_values[l]=value;
	}
	
//add the functions from the mods to the layer
function addNew(i) {
	var qq;
	for (qq = 0; qq < modules_names.length; qq++) {
	//	alert(this+'.'+modules_names[qq]+' = '+modules_values[qq]);
		eval('this.'+modules_names[qq]+' = '+modules_values[qq]);
		}
	}
	
	
	
//runMe - passes in an Array, splits it into codette, evals it and then passes the rest on
function runMe(codette){
if(codette && codette != "undefined" && codette != "end"){
//	alert('1:'+codette);
			codette = codette.split("|")
			direction = codette[0];
			distance = codette[1];
			speed = codette[2];
			if (direction == "jump") {
				setTimeout(distance,speed);				
				}
			if (direction == "pause") {
				codette_pause = codette.reverse();
				codette_pause.length = codette_pause.length - 3;
				codette_pause = codette_pause.reverse();
				codette_pause = codette_pause.join("|");
				setcodette = 'runMe("'+codette_pause+'")';
				setTimeout(setcodette,speed);
	//			alert(setcodette);
				}
			if (direction && direction != "jump" && direction != "pause") {
				codette.reverse();
				codette.length = codette.length - 3;
				codette_jump = codette.reverse();
				codette_jump = codette_jump.join('|');
		//		alert(codette_jump);
				setcodette = direction+'('+distance+','+speed+',"'+codette_jump+'")';
				setTimeout(setcodette,speed);
				}
			}
		}
	
	
		
//actually constructs the layer object.  Note: do not name the layer the same as your DIV id -
//IE 4 will crash.
function layer(name) {
//	init_layer(name);
	this.name = name;
	this.layer = name_layer(name);
	this.obj_name = 'layer_' + name;
	if (document.getElementById) {
	eval('this.top = '+this.layer+'.top');
	eval('this.left = '+this.layer+'.left');
	eval('this.height = '+this.layer+'.height');
	eval('this.width = '+this.layer+'.width');
	eval('myclip = '+this.layer+'.clip');
	clip = getClipping(myclip);
	eval('this.clipTop = '+clip[0]);
	eval('this.clipRight = '+clip[1]);
	eval('this.clipBottom = '+clip[2]);
	eval('this.clipLeft = '+clip[3]);
	eval('this.zIndex = '+this.layer+'.zIndex');
	eval('this.visibility = '+this.layer+'.visibility');
	}
	else if (document.layers) {
	eval('this.top = '+this.layer+'.top');
	eval('this.left = '+this.layer+'.left');
	eval('this.height = '+this.layer+'.clip.height');
	eval('this.width = '+this.layer+'.clip.width');
	eval('this.clipTop = '+this.layer+'.clip.top');
	eval('this.clipLeft = '+this.layer+'.clip.left');
	eval('this.clipBottom = '+this.layer+'.clip.bottom');
	eval('this.clipRight = '+this.layer+'.clip.right');
	eval('this.zIndex = '+this.layer+'.zIndex');
	eval('this.visibility = '+this.layer+'.visibility');
	}
	else if(document.all) {
	eval('this.top = '+this.layer+'.pixelTop');
	eval('this.left = '+this.layer+'.pixelLeft');
	eval('this.height = '+this.layer+'.pixelHeight');
	eval('this.width = '+this.layer+'.pixelWidth');
	eval('myclip = '+this.layer+'.clip');
	clip = getClipping(myclip);
	eval('this.clipTop = '+clip[0]);
	eval('this.clipRight = '+clip[1]);
	eval('this.clipBottom = '+clip[2]);
	eval('this.clipLeft = '+clip[3]);
	eval('this.zIndex = '+this.layer+'.zIndex');
	eval('this.visibility = '+this.layer+'.visibility');
	}
	this.speed = 2;
	this.refresh = layer_refresh;
	this.extend = layer_extend;
	this.runMe = runMe;
	this.report = layer_report;
	this.setWatch = setWatch;
	this.load = layer_load;
	this.ieFinish = layer_ieFinish;
	this.addNew = addNew;
	this.addNew(); //must do this last
}

//add elements (and hopefully their properties) to a layer
function layer_extend(layer_element) {
//alert(layer_element);
	if (document.getElementById) {
		layer_element_place = 'document.getElementById("'+layer_element+'")';
		}
	if (document.all) {
		layer_element_place = 'document.all["'+layer_element+'"]';
		}
	if (document.layers) {
		layer_element_place = this.layer+'.document.'+layer_element;
		}
	eval(this.obj_name +'.'+layer_element +'='+ layer_element_place);
	//alert(this.obj_name +'.'+layer_element +'='+ layer_element_place);
	}
	
//keeping this only for caution's sake - it's been deprecated.
//initialize the layer_refer to handle dom semantics
function init_layer(name) {
  if (document.getElementById) {
  	return('document.getElementById("'+name+'").style');
	}
  if (document.layers) {
    layer_refer = 'document.layers["'+name+'"]';
	}
  if (document.all) {
    layer_refer = 'document.all["' + name + '"].style';
	}
}

//initialize the this.layer property
function name_layer(name) {
  if (document.getElementById) {
  	return('document.getElementById("'+name+'").style');
	}
  else if (document.layers) {
	return('document.layers["'+name+'"]');
 	}
  else if (document.all) {
	return('document.all["' + name + '"].style');
	}
}

//very important.  This function refreshes what was just changed with the
//JS object. Essentially maintains the state of the variables for the layer.
function layer_refresh() {
	init_layer(this.name);
	if (document.getElementById) {
	eval('this.top = '+this.layer+'.top');
	eval('this.left = '+this.layer+'.left');
	eval('this.height = '+this.layer+'.height');
	eval('this.width = '+this.layer+'.width');
	eval('myclip = '+this.layer+'.clip');
	clip = getClipping(myclip);
	eval('this.clipTop = '+clip[0]);
	eval('this.clipRight = '+clip[1]);
	eval('this.clipBottom = '+clip[2]);
	eval('this.clipLeft = '+clip[3]);
	eval('this.zIndex = '+this.layer+'.zIndex');
	eval('this.visibility = '+this.layer+'.visibility');
	}
	else if (document.layers) {
		eval('this.top = '+this.layer+'.top');
		eval('this.left = '+this.layer+'.left');
		eval('this.height = '+this.layer+'.height');
		eval('this.width = '+this.layer+'.width');
		eval('this.clipTop = '+this.layer+'.clip.top');
		eval('this.clipLeft = '+this.layer+'.clip.left');
		eval('this.clipBottom = '+this.layer+'.clip.bottom');
		eval('this.clipRight = '+this.layer+'.clip.right');
		eval('this.zIndex = '+this.layer+'.zIndex');
		eval('this.visibility = '+this.layer+'.visibility');	
		}
	else if (document.all) {
		eval('this.top = '+this.layer+'.pixelTop');
		eval('this.left = '+this.layer+'.pixelLeft');
		eval('this.height = '+this.layer+'.pixelHeight');
		eval('this.width = '+this.layer+'.pixelWidth');
		eval('myclip = '+this.layer+'.clip');
		clip = getClipping(myclip);
		eval('this.clipTop = '+clip[0]);
		eval('this.clipRight = '+clip[1]);
		eval('this.clipBottom = '+clip[2]);
		eval('this.clipLeft = '+clip[3]);
		eval('this.zIndex = '+this.layer+'.zIndex');
		eval('this.visibility = '+this.layer+'.visibility');	
		}
	}

//support function - not really for external use.  returns the IE css clip values.
//someone ask MS why they combined four variables into one, please?
//modified from cbdhtml.js
function getClipping(ieclipstr) {
  ieclip = new Array();
  i = ieclipstr.indexOf("(");
  ieclip[0] = parseInt(ieclipstr.substring(i + 1, ieclipstr.length), 10);
  i = ieclipstr.indexOf(" ", i + 1);
  ieclip[1] = parseInt(ieclipstr.substring(i + 1, ieclipstr.length), 10);
  i = ieclipstr.indexOf(" ", i + 1);
  ieclip[2] = parseInt(ieclipstr.substring(i + 1, ieclipstr.length), 10);
  i = ieclipstr.indexOf(" ", i + 1);
  ieclip[3] = parseInt(ieclipstr.substring(i + 1, ieclipstr.length), 10);
  return(ieclip);
}

//support function for debugging purposes.  will send an alert of current layer state
function layer_report() {
	alert("-REPORT-\nname:"+this.name+"\nobject name:"+this.obj_name+"\nlayer name:"+this.layer+"\ntop:"+this.top+"\nleft:"+this.left);
	alert("height:"+this.height+"\nwidth:"+this.width+"\nvisibility:"+this.visibility+"\nzindex:"+this.zIndex);
	}

	
//allows for event watches to be set to specific actions(other functions)
function setWatch(event,action) {
	if (document.layers) {
		eval("document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP | Event.MOUSEOVER | Event.MOUSEOUT)");
		eval("document.captureEvents(Event.ONCLICK)");
		}
	eval("document."+event+" = "+action);
	}

	
function setPager1(top,left,bottom,right,action) {
	thisArray = new Array(top,left,bottom,right,action);
	pl = pager1_values.length;
	pager1_values[pl]=thisArray;
	}
	
function catchPager1(event) {
	if(document.layers){thisY=event.pageY;thisX=event.pageX;}
	else if(document.all){thisY=window.event.clientY;thisX=window.event.clientX;}
	for (plv = 1; plv < pager1_values.length; plv++) {
		eval("pagerTop = " + pager1_values[plv][0]);
		eval("pagerLeft = " + pager1_values[plv][1]);
		eval("pagerBottom = " + pager1_values[plv][2]);
		eval("pagerRight = " + pager1_values[plv][3]);
		if(thisY > pagerTop && thisY < pagerBottom
			&& thisX > pagerLeft && thisX < pagerRight) {eval(pager1_values[plv][4]);}
		}
	}

function setPager2(top,left,bottom,right,action) {
	thisArray = new Array(top,left,bottom,right,action);
	pl = pager2_values.length;
	pager2_values[pl]=thisArray;
	}
	
function catchPager2(event) {
	if(document.layers){thisY=event.pageY;thisX=event.pageX;}
	else if(document.all){thisY=window.event.clientY;thisX=window.event.clientX;}
	for (plv = 1; plv < pager2_values.length; plv++) {
		eval("pagerTop = " + pager2_values[plv][0]);
		eval("pagerLeft = " + pager2_values[plv][1]);
		eval("pagerBottom = " + pager2_values[plv][2]);
		eval("pagerRight = " + pager2_values[plv][3]);
		if(thisY > pagerTop && thisY < pagerBottom
			&& thisX > pagerLeft && thisX < pagerRight) {eval(pager2_values[plv][4]);}
		}
	}

function setPager3(top,left,bottom,right,action) {
	thisArray = new Array(top,left,bottom,right,action);
	pl = pager3_values.length;
	pager3_values[pl]=thisArray;
	}
	
function catchPager3(event) {
	if(document.layers){thisY=event.pageY;thisX=event.pageX;}
	else if(document.all){thisY=window.event.clientY;thisX=window.event.clientX;}
	for (plv = 1; plv < pager3_values.length; plv++) {
		eval("pagerTop = " + pager3_values[plv][0]);
		eval("pagerLeft = " + pager3_values[plv][1]);
		eval("pagerBottom = " + pager3_values[plv][2]);
		eval("pagerRight = " + pager3_values[plv][3]);
		if(thisY > pagerTop && thisY < pagerBottom
			&& thisX > pagerLeft && thisX < pagerRight) {eval(pager3_values[plv][4]);}
		}
	}

//loads the HTML from an external file into the layer (overwrites)
//modified from dynAPI
function layer_load(file,width,buffer) {
if(!width){width = this.width;}
if(document.layers){
	eval(this.layer+'.load("'+file+'",'+width+')');
	}
if(document.all){
	eval(buffer + ".location = '" + file + "'");
	}
}

//support function for srcLoad.  Used in the external file to notify IE that
//it is done loading.  Not used in NS.
//modified from dynAPI
function layer_ieFinish(buffer) {
	if(document.all){eval(this.name + '.innerHTML = ' + buffer + ' .body.innerHTML')};
	}
	
//create a new layer.  modified version of ds's createLayer
function createNewLayer(attr,content,codette) {
	lyrId = attr[0];
	lyrLeft = attr[1];
	lyrTop = attr[2];
	lyrWidth = attr[3];
	lyrHeight = attr[4];
	lyrBgColor = attr[5];
	lyrVisibility = attr[6];
	lyrZIndex = attr[7];
	if (document.layers) {
		var lyr = document.layers[lyrId] = new Layer(lyrWidth)
		lyr.name = lyrId 
		lyr.left = lyrLeft
		lyr.top = lyrTop
		if (lyrWidth!=null) lyr.clip.width = lyrWidth
		if (lyrHeight!=null) lyr.clip.height = lyrHeight
		if (lyrBgColor!=null) lyr.bgColor = lyrBgColor
		if (lyrVisibility!=null) lyr.visibility = lyrVisibility
		if (lyrZIndex!=null) lyr.zIndex = lyrZIndex
		if (content) {
			content = "<body>"+content+"</body>";
			eval('document.layers["'+lyrId+'"].document.open()');
			eval('document.layers["'+lyrId+'"].document.write("'+content+'")');
			eval('document.layers["'+lyrId+'"].document.close()');
			eval('a = document.layers["'+lyrId+'"].zIndex');
		}
	}
	else if (document.all) {
		var str = '\n<DIV id='+lyrId+' style="position:absolute; left:'+lyrLeft+'; top:'+lyrTop+'; width:'+lyrWidth
		if (lyrHeight!=null) {
			str += '; height:'+lyrHeight
			str += '; clip:rect(0,'+lyrWidth+','+lyrHeight+',0)'
		}
		if (lyrBgColor!=null) str += '; background-color:'+lyrBgColor		
		if (lyrZIndex!=null) str += '; zIndex:'+lyrZIndex
		if (lyrVisibility) str += '; visibility:'+lyrVisibility
		str += ';">'+((content)?content:'')+'</DIV>'
		document.body.insertAdjacentHTML("BeforeEnd",str)
	}
	eval('layer_'+lyrId+' = new layer("'+lyrId+'")');
	if (codette){runMe(codette);}
}


function destroyLayer(layer) {
	layer.hide()
}
//end glimmer

//the above is not the sole property of anyone.

//Bugs and Updates
//Date: Aug, 26, 1999
//Added arc methods, setDepth method, updated rotate method.
//began 5th generation browser testing.

//Date: Aug, 12, 1999
//Changed destroyLayer just to use hide Layer.  It accomplishes
//roughly the same thing since layers can't be destroyed.

//Date: Around Aug 5, 199
//Fixed layer_overwrite which suffered from the odd bug
//that it wouldn't write in Netscape

//will be updating the header with the DynAPI disclaimer.

//Date: Around Aug, 1, 1999
//updated the watch and pager functions.  Glimmer now has access to three
//independant pagers which can attach themselves to watches.

//Date: Jul, 29, 1999
// *finished the first version of createLayer, basically a modified version of
//  DynAPI's


//Date: Jul, 26, 1999
// *fixed srcLoad/ieSrcFin function so that it is target independant
// *added new comments

//Date: Unknown
//I just started doing this in the source, so here is a quick rundown of previous
//glimmer changes...

// *added setWatch function.  First time dragndrop works right.  demo to follow
// *added srcLoad functions.  This is a heavily modified version from Dynamic Duo.  Will
//  send DS changes and see if he needs a GPL statement added
// *fixed stupid move bug-one set of directions were stuck at a certain speed
// *Val added rotate, color_ripple, other neat fx functions
// *Split glimmer into core library and mods
// *added effects of certain varieties
// *core library, JS Object to CSS 'connections' working

/////Versioning info:
// 0.0 - 0.5 : original dHTML code snippets
// 0.6 - 1.0 : glimmer layer object
// 1.1 - 1.5 : combination of glimmer layer object and all the methods
// 1.5 - 1.7.5 : glimmer was split into the core library and mods.  glimmer now extensible
// 1.7.5 - 2.0 : the writing of decent docs, tutorials, and publishing of the code.  2.0 being the first major 'freeze'.