//Moving Focus for Accessibility 1.1.3
//C. Blouch
//May 24 2006

//Return the object specified by ID J
function ge(j){return document.getElementById(j)}
//Return a handle to the style specified by ID J
function r(o,c){if(o)o.innerHTML=c}

//Called on pageload
function init(){
	//Add an onclick handler to the update buttons
	ge("add").onclick=addf;
	ge("delete").onclick=deletef;
	ge("focusme").onclick=moveit;
	ge("both").onclick=addmove;
}

//Move the focus to a particular object
function moveit(){
	//set o to the object we want to focus on
	var o=document.getElementsByClassName(document.forms.theform.elements.theClass.value)[0];
	//Pass the object to move_focus
	move_focus(o);
	return false;
}

//make a new method to get DOM objects by Class
document.getElementsByClassName=function(c){
	var found=new Array();
	//Get all the elements in the document
	var everything=document.getElementsByTagName("*");
	//Loop through all the elements and store any which have a class of className
	for(var i=0;i<everything.length;i++){
		if(everything[i].className.search("(\\b)"+c+"(\\b)")>-1)found[found.length]=everything[i];
	}
	return found;
}

//Move focus to any item in the DOM passed in.
var move_focus_obj; //Temp global var to hold focusable object
function move_focus(dom_object,tabvalue){
	//If this DOM object doesn't already have a tabindex attribute then add one

	//Firefox
	//getAttribute returns a null when there is no tabIndex, so go ahead and add it
	//If it isn't null then there is a an existing tabIndex so leave things alone

	//IE
	//getAttribute returns a 0 even when there is no tabIndex so we don't know if tabIndex DNE or if it was set legitimately
	//to 0 in the HTML. So First part of If should fail in IE as 0!=null. The second part of the If checks whether the
	// tabIndex value was specified or is just a default value. If default we go ahead and add a tabIndex.
	//Also note that "tabIndex" must have the capital I to work in IE, even though the html is specified as "tabindex"

	//Note:
	//Doing a getAttributeNode().specified in FF on a null node breaks, but this should never happen.
	//
	//If the node's tabIndex is null the first part of the if should evaluate to true,
	//causing execution to immediately flow into the body of the if.
	//
	//If the node's tabIndex is !null then the both the getAttribute() and !getAttributeNode().specified should evaluate to false
	//leaving the existing tabIndex alone.
	//Also, because the node's tabIndex is !null the getAttributeNode().specified no longer fails in FF.

	//These items don't need tabindex added. If first checks to make sure we don't need to bother modifying attributes
	var focus_exceptions={A:1,AREA:1,BUTTON:1,INPUT:1,OBJECT:1,SELECT:1,TEXTAREA:1};
	
	//If we are not modifying a node that needs no tabindex hackery or we are passed in a tabvalue then modify the node
	if(
		(tabvalue ||
		!focus_exceptions[dom_object.nodeName] && 
		(dom_object.getAttribute("tabIndex")==null || !dom_object.getAttributeNode("tabIndex").specified))
		)
	{
		errlog("tabindex is:"+dom_object.getAttribute("tabindex"));
		//If we aren't passed in a value to set tabindex to then default to -1
		if(!tabvalue)tabvalue=-1;
		errlog("adding tabindex of "+tabvalue);
		dom_object.setAttribute("tabIndex",tabvalue);
	}
	errlog("moving focus to object");
	//Why are we calling focus twice? This works around an IE bug where the first .focus is randomly ignored
	//Doesn't hurt anything to send focus to the same thing twice and turned out to be more reliable than
	//various setTimeout hacks other folks have used. Go Microsoft!
	if(document.all)dom_object.focus();
	//Some browsers got confused if we did focus right away so this 0ms delay hack seems to help them out
	move_focus_obj=dom_object;
	setTimeout("move_focus_obj.focus()",0);
	
}
//They clicked the button so let's update
function deletef(){
	var o,y;
	//Get a handle to the second column
	o=ge("column2");
	//Grab the list of DIVs from that column
	y=o.getElementsByTagName("div");
	//Delete the second instance if there are at least 3 items
	if(y.length>2){
		errlog("Destroying middle DIV");
		o.removeChild(y[1]);
	}else{
		errlog("Not enough DIVs to delete one out of the middle");
	}
	return false;
}
function addf(){
	var o,y,e,s;
	//Grab HTML to be inserted
	s=document.forms.theform.elements.thehtml.value;
	//Get a handle to the second column
	o=ge("column2");
	//Grab the list of DIVs from that column
	y=o.getElementsByTagName("div");
	//Create a new DIV
	errlog("Creating new DIV");
	var e=document.createElement("div");
	//Set some attributes for the DIV
	e.setAttribute("class","box four");
	//And just to make IE happy we do it their nonstandard way
	e.setAttribute("className","box four");
	//Append the DIV to the list
	errlog("Inserting new DIV");
	o.insertBefore(e,y[1]);
	//Inject new content in DIV
	errlog("Updating innerHTML");
	e.innerHTML=s;
	return false;
}

function addmove(){
	addf();
	moveit();
}

//Add function fn to be called when object o fires event et
//Handles both the standard addEventListner and IE attachEvent ways to do this.
//Works around a pile of IE bugs/quirks with attachEvent
function ae(o,et,fn){
	var x;
	if(x=o.addEventListener)x(et,fn,0);
	else if(x=o.attachEvent){
		o['e'+et+fn]=fn;
		o[et+fn]=function(){o['e'+et+fn](window.event);}
		x('on'+et,o[et+fn]);
	}
}
//When the window fires an onload event, call the function init()
ae(window,'load',init);

// Manage Logging
//////////////////////////////
var e_log="JavaScript Diagnostics<br>";
function errlog(t){
	var mn,se,ml;
	mn=new Date().getMinutes();
	se=new Date().getSeconds();
	ml=new Date().getMilliseconds();
	e_log="<b>"+mn+"m"+se+"s"+ml+"ms:</b> "+t+"<br>"+e_log;
	document.getElementById("errlog").innerHTML=e_log;
}
