/*!
**********************************************************************
@file WizardAccessibilityManager1.js

Copyright 2003-2008 Adobe Systems Incorporated.                     
All Rights Reserved.                                                
                                                                    
NOTICE: All information contained herein is the property of Adobe   
Systems Incorporated.                                                                                                                    

***********************************************************************
*/
/**
Wizard Accessibility Manager1
Trivia :: The number 1 in all my widgets signifies that all these are first time written original code. (egirishg@adobe.com).
They are also not there in cs3 installers. You can also look at them as v1.0 release of javascript widgets api.
*/

var ePageRef = document.getElementById("container");
var eFullArray;

/*ON THEIR OWN, THEY MEAN SOMETHING*/

var eTAB = 9;//SWITCH FOCUS ONLY
var eSPACE = 32;//SELECT CURRENTLY FOCUSED ELEMENT
var eESCAPE = 27;//MAPPED TO AN ELEMENT OF CURRENT PAGE
var eENTER = 13;//MAPPED TO AN ELEMENT OF CURRENT PAGE

/*ON THEIR OWN, THEY MEAN SOMETHING*/
var eLEFTARROW = 37;//MOVE FOCUS TO PREVIOUS SIMILAR ELEMENT
var eUPARROW = 38;//MOVE FOCUS TO NEXT SIMILAR ELEMENT
var eRIGHTARROW = 39;//MOVE FOCUS TO NEXT SIMILAR ELEMENT
var eDOWNARROW = 40;//MOVE FOCUS TO PREVIOUS SIMILAR ELEMENT

/*ONLY WITH ALT KEY, THE RANGE OF ALPHABETS AND NUMBERS MEAN SOMETHING*/
var eALT = 18;
var eA = 65;
var eZ = 90;
var ea = 97;
var ez = 122;
var e0 = 48;
var e9 = 57;
var e0_numpad = 96;
var e9_numpad = 105;

function WizardAccessibilityManager1()
{
	this.SetFocusStyleGlobal("1px solid white","none");
	this.CurrentFocusElementIndex = -1;
	this.EventContainer = document;
	this.PageDefaultFocusElement = null;//document.body;
	this.CurrentFocusElement = this.PageDefaultFocusElement;
	this.ClearAllElements();
}

WizardAccessibilityManager1.prototype.ClearAllElements = function()
{
	this.PageAccessibleElementsArray = new Array();
	this.AddElement({element:this.PageDefaultFocusElement,hotkey:'0',virtualtype:'EventContainer'});
}

WizardAccessibilityManager1.prototype.AddElementSet = function(ElementSet)
{
	for(var i=0;i<ElementSet.length;i++)
	{
		this.AddElement(ElementSet[i]);
	}
}

WizardAccessibilityManager1.prototype.RemoveAllElements = function()
{
	while (this.PageAccessibleElementsArray.length > 0)
	{
		var E = this.PageAccessibleElementsArray.pop();

		E.onfocus = E.prev_onfocus;
		E.onclick = E.prev_onclick;
		E.onkeydown = E.prev_onkeydown;
		E.Index = null;
		E.WizardAccessibilityManager = null;
	}
	this.CurrentFocusElementIndex = -1;
	// Reset default focus Elements
	this.SetPageDefaultEnterElement(null);
	this.SetPageDefaultEscapeElement(null);
	this.SetPageDefaultFocusElement(null);
	this.ClearPageFocus();
}

/*_BEGIN_GLOBAL_TEMPLATE
EObjectRef =	{
					element			:	_,
					hotkey			:	_,	//(& localization)
					focal			:	_,
					nofocal			:	_,
					virtualtype		:	_,
					//jaws label	: _		//(& localization)
				};
ElementSet =	[
					EObjectRef1,
					EObjectRef2
				];
_END_GLOBAL_TEMPLATE*/

WizardAccessibilityManager1.prototype.AddElement = function(EObjectRef)//take care of real properties like taborder, tabindex and label which jaws might be using
{
	var E = EObjectRef.element;

	if (E == null)
		return;

	E.WizardAccessibilityManager = this;
	if(E.style)
	{
	}
	else
	{
		E.style = new Object();
	}
	// New one?
	if (E.Index == null) {
		E.Index = this.PageAccessibleElementsArray.length;
		this.PageAccessibleElementsArray.push(E);
		E.oldborder = E.style.border;
		// Add event handling for element (not for body 0-index)
		E.prev_onfocus = E.onfocus;
		E.prev_onclick = E.onclick;
		E.prev_onkeydown = E.onkeydown;

		var thisWAM = this;
		E.onfocus = function()
		{
			thisWAM.SetFocusElement(this);
			if (this.prev_onfocus)
				this.prev_onfocus();
		};

		E.onclick = function()
		{
			thisWAM.SetFocusElement(this);
			if (this.prev_onclick)
				this.prev_onclick();
		};
		if (EObjectRef.virtualtype == 'InputField') {
			E.onkeydown = function()
			{
				var ekeycode = event.keyCode;
				var econtrolkey = event.ctrlKey;
				var ealtkey = event.altKey;
				var eshiftkey = event.shiftKey;
				var emetakey = event.metaKey;
				
				if(ekeycode==eENTER && !econtrolkey)
				{
					if (!this.isMultiLine || this.readOnly) {
						thisWAM.OnEnterGlobal();
						event.cancelBubble = true;
						event.returnValue = false;
					}
				}
				else if(ekeycode==eESCAPE)
				{
					thisWAM.OnEscapeGlobal();
					event.cancelBubble = true;
					event.returnValue = false;
				}
				else if(ealtkey && thisWAM.IsAlphaNumeric(ekeycode))
				{
					thisWAM.OnHotKeyPressGlobal(ekeycode);
					event.cancelBubble = true;
					event.returnValue = false;
				}
				if (this.prev_onkeydown)
					this.prev_onkeydown();
			};
		}
	}
	E.HasStyleRec = function(style, value)
	{
		var element = this;
		var bHasStyle = false;
		while (element && !bHasStyle) {
			bHasStyle = (element.currentStyle[style] == value);
			element = element.parentElement;
		}
		return bHasStyle;
	}
	E.IsDisabled = function()
	{
		var element = this;
		var bDisabled = false;
		while (element && !bDisabled) {
			bDisabled = element.disabled;
			element = element.parentElement;
		}
		return bDisabled;
	}
	E.CanTakeFocus = function()
	{
		return !(this.HasStyleRec("display", "none") || this.IsDisabled());
	}
	this.SetHotKeyElemental(E,EObjectRef.hotkey);
	if (EObjectRef.virtualtype == 'InputField') {
		E.dontDrawFocusRect = true;
	}
	this.SetFocusStyleElemental(E,EObjectRef.focal,EObjectRef.nofocal);
	E.virtualtype=EObjectRef.virtualtype;
	E.tabIndex = E.Index;
}

WizardAccessibilityManager1.prototype.ClearFocusBorderElemental = function(E)
{
	if (E.dontDrawFocusRect)
		return;
	if(E.oldborder != null)
		E.style.border = E.oldborder;
	else
	{
		if(E.NoFocusStyleGlobal)
			E.style.border = E.NoFocusStyleGlobal;
		else
			E.style.border = this.NoFocusStyleGlobal;
	}
//	E.blur();
}

WizardAccessibilityManager1.prototype.MakeFocusBorderElemental = function(E)
{
	if (E.dontDrawFocusRect)
		return;
	if(E.FocusStyleGlobal != null)
		E.style.border = E.FocusStyleGlobal;
	else
		E.style.border = this.FocusStyleGlobal;
}

WizardAccessibilityManager1.prototype.ClearPageFocus = function()
{
	this.SetFocusOnDefaultElement();
}

WizardAccessibilityManager1.prototype.SetFocusElement = function(E)
{
	if(E.Index == null || this.CurrentFocusElementIndex==E.Index)
		return;
	if(this.CurrentFocusElement)
		this.ClearFocusBorderElemental(this.CurrentFocusElement);
	this.CurrentFocusElementIndex=E.Index;
	this.MakeFocusBorderElemental(this.GetFocusElement());
	this.CurrentFocusElement=E;
	if (!this.bDontCallFocus)
		E.focus();
}

WizardAccessibilityManager1.prototype.GetFocusElement = function()
{
	if (this.PageAccessibleElementsArray.length == 0 || this.CurrentFocusElementIndex < 0)
		return null;
	return this.PageAccessibleElementsArray[this.CurrentFocusElementIndex];
}

WizardAccessibilityManager1.prototype.FocusPreviousElement = function(etype)
{
	if (this.PageAccessibleElementsArray.length == 0)
		return;

	var currentFocusElementIndex = this.CurrentFocusElementIndex;

	if (currentFocusElementIndex < 0) // Currently no focus
		currentFocusElementIndex = 0; // Start from beginning
	for(var i=(currentFocusElementIndex-1); i!=currentFocusElementIndex;i--)
	{
		if (i < 0)
			i=(this.PageAccessibleElementsArray.length)-1;
		var E = this.PageAccessibleElementsArray[i];

		if(etype && E.virtualtype!=etype)
		{
			continue;
		}
		if (E.CanTakeFocus()) {
			if(etype == 'WizardRadioButton1') {
				this.ClickElement(E, true);
			}
			else {
				this.SetFocusElement(E);
			}
			return;
		}
	}
	return;
}

WizardAccessibilityManager1.prototype.FocusNextElement = function(etype)
{
	if (this.PageAccessibleElementsArray.length == 0)
		return;

	var currentFocusElementIndex = this.CurrentFocusElementIndex;

	if (currentFocusElementIndex < 0) // Currently no focus
		currentFocusElementIndex = 0; // Start from beginning
	for(var i=(currentFocusElementIndex+1); i!=currentFocusElementIndex;i++)
	{
		if (i >= this.PageAccessibleElementsArray.length)
			i=0;
		var E = this.PageAccessibleElementsArray[i];

		if(etype) {
			if (E.virtualtype!=etype)
				continue;
		}
		if (E.CanTakeFocus()) {
			if(etype == 'WizardRadioButton1') {
				this.ClickElement(E, true);
			}
			else {
				this.SetFocusElement(E);
			}
			return;
		}
	}
	return;
}

WizardAccessibilityManager1.prototype.FocusPreviousSimilarElement = function()
{
	if (this.PageAccessibleElementsArray.length == 0 || this.CurrentFocusElementIndex < 0)
		return;
	var E = this.PageAccessibleElementsArray[this.CurrentFocusElementIndex];
	if (!E.dontDrawFocusRect) {
		this.FocusPreviousElement(E.virtualtype);
	}
}

WizardAccessibilityManager1.prototype.FocusNextSimilarElement = function()
{
	if (this.PageAccessibleElementsArray.length == 0 || this.CurrentFocusElementIndex < 0)
		return;
	var E = this.PageAccessibleElementsArray[this.CurrentFocusElementIndex];
	if (!E.dontDrawFocusRect) {
		this.FocusNextElement(E.virtualtype);
	}
}

WizardAccessibilityManager1.prototype.ClickElement = function(E, bDontCheckCanTakeFocus)
{
	if (bDontCheckCanTakeFocus || E.CanTakeFocus()) {
		this.SetFocusElement(E);
		E.fireEvent("onclick");
	}
}

WizardAccessibilityManager1.prototype.SetPageDefaultFocusElement = function(PageDefaultFocusElement)
{
	this.PageDefaultFocusElement = PageDefaultFocusElement;
}

WizardAccessibilityManager1.prototype.SetPageDefaultEscapeElement = function(PageDefaultEscapeElement)
{
	this.PageDefaultEscapeElement = PageDefaultEscapeElement;
}

WizardAccessibilityManager1.prototype.SetPageDefaultEnterElement = function(PageDefaultEnterElement)
{
	this.PageDefaultEnterElement = PageDefaultEnterElement;
}

WizardAccessibilityManager1.prototype.GetPageDefaultFocusElement = function()
{
	return this.PageDefaultFocusElement;
}

WizardAccessibilityManager1.prototype.SetFocusStyleGlobal = function(focal,nofocal)
{
	this.FocusStyleGlobal = focal;
	this.NoFocusStyleGlobal = nofocal;
}

WizardAccessibilityManager1.prototype.SetFocusStyleElemental = function(E,focal,nofocal)
{
	E.FocusStyleGlobal = focal;
	E.NoFocusStyleGlobal = nofocal;
}

WizardAccessibilityManager1.prototype.SetHotKeyElemental = function(E,key)
{
	E.hotkey=key;
}

WizardAccessibilityManager1.prototype.IsAlphaNumeric = function(ekeycode)
{
	if(((ekeycode >= eA) && (ekeycode <= eZ)) || ((ekeycode >= ea) && (ekeycode <= ez)))
		return true;
	if(((ekeycode >= e0) && (ekeycode <= e9)) || ((ekeycode >= e0_numpad) && (ekeycode <= e9_numpad)))
		return true;
	return false;
}

WizardAccessibilityManager1.prototype.OnTabGlobal = function(eshiftkey)
{
	this.bDontCallFocus = true;
	if(eshiftkey)
	{
		this.FocusPreviousElement();
	}
	else
	{
		this.FocusNextElement();
	}
	this.bDontCallFocus = false;
}

WizardAccessibilityManager1.prototype.OnSpaceGlobal = function()
{
	if (this.PageAccessibleElementsArray.length == 0 || this.CurrentFocusElementIndex < 0)
		return;
	this.ClickElement(this.PageAccessibleElementsArray[this.CurrentFocusElementIndex]);
}

WizardAccessibilityManager1.prototype.OnArrowGlobal = function()
{
}

WizardAccessibilityManager1.prototype.OnEnterGlobal = function()
{
	if (this.PageAccessibleElementsArray.length == 0 || this.CurrentFocusElementIndex < 0)
		return;
	var E = this.PageAccessibleElementsArray[this.CurrentFocusElementIndex];
	if (E.virtualtype == 'WizardButton1')
		this.ClickElement(E);
	else if (this.PageDefaultEnterElement)
		this.ClickElement(this.PageDefaultEnterElement);
}

WizardAccessibilityManager1.prototype.OnEscapeGlobal = function()
{
	if (this.PageDefaultEscapeElement)
		this.ClickElement(this.PageDefaultEscapeElement);
}

WizardAccessibilityManager1.prototype.OnHotKeyPressGlobal = function(ekeycode)
{
	this.hotKeyCode = ekeycode;
	var thisCB = this;
	// Using timeout as IE causing events to be mess up.
	setTimeout(function() {thisCB.OnHotKeyPressGlobalEx();}, 1);
}

WizardAccessibilityManager1.prototype.OnHotKeyPressGlobalEx = function()
{
	var ekeycode = this.hotKeyCode;

	if (ekeycode) {
		for(var i=0;i<this.PageAccessibleElementsArray.length;i++)
		{
			var E = this.PageAccessibleElementsArray[i];

			if(E.hotkey && E.hotkey.charCodeAt()==ekeycode)
			{
				this.ClickElement(E);
				break;
			}
		}
	}
	this.hotKeyCode = null;
}

WizardAccessibilityManager1.prototype.OnClickGlobal = function()
{
}

WizardAccessibilityManager1.prototype.MakeHotKeysAvailable = function()
{
	var thisWAM = this;
	this.EventContainer.onkeyup = function()
	{
		var ekeycode = event.keyCode;

		if(ekeycode==eSPACE)
		{
			thisWAM.OnSpaceGlobal();
			event.cancelBubble = true;
			event.returnValue = false;
		}
	};
	this.EventContainer.onkeydown = function()
	{
		var ekeycode = event.keyCode;
		var econtrolkey = event.ctrlKey;
		var ealtkey = event.altKey;
		var eshiftkey = event.shiftKey;
		var emetakey = event.metaKey;
		
		if(ekeycode==eSPACE)
		{
			event.cancelBubble = true;
			event.returnValue = false;
		}
		else if(ekeycode==eTAB)
		{
			thisWAM.OnTabGlobal(eshiftkey);
		}
		else if(ekeycode==eENTER)
		{
			thisWAM.OnEnterGlobal();
			event.cancelBubble = true; // Events from alert window are detected in alert and also passed to main window, to prevent double handling
			event.returnValue = false;
		}
		else if(ekeycode==eESCAPE)
		{
			thisWAM.OnEscapeGlobal();
			event.cancelBubble = true; // Events from alert window are detected in alert and also passed to main window, to prevent double handling
			event.returnValue = false;
		}
		else if(ekeycode==eLEFTARROW || ekeycode==eUPARROW)
		{
			thisWAM.OnArrowGlobal();
			thisWAM.FocusPreviousSimilarElement();
		}
		else if(ekeycode==eRIGHTARROW || ekeycode==eDOWNARROW)
		{
			thisWAM.OnArrowGlobal();
			thisWAM.FocusNextSimilarElement();
		}
		else if(ealtkey && thisWAM.IsAlphaNumeric(ekeycode))
		{
			thisWAM.OnHotKeyPressGlobal(ekeycode);
			event.cancelBubble = true; // Events from alert window are detected in alert and also passed to main window, to prevent double handling
			event.returnValue = false;
		}
	};
}

WizardAccessibilityManager1.prototype.SetFocusOnDefaultElement = function()
{
	var E = this.GetPageDefaultFocusElement();

	if (E != null && E.CanTakeFocus()) {
		this.SetFocusElement(E);
	}
	else {
		this.EventContainer.focus(); // Put focus on document if none of the element can take focus.
	}
}

WizardAccessibilityManager1.prototype.RunPageControl = function()
{
	this.SetFocusOnDefaultElement();
	this.MakeHotKeysAvailable();
}
