/*
	ajaxTags.js
	
	This file contains client-side functionality for the JSP <ajax> tags.
*/

/*
	This function inserts a function into the chain of functions to be executed
	when the current page is finished loading.
*/
function cxajax_addWindowLoadEvent(func)
{
	var		oldonload = window.onload;
	if (typeof window.onload != 'function')
	{
		window.onload = func;
	}
	else
	{
		window.onload = function()
		{
			if (oldonload)
			{
				oldonload();
			}
			func();
		}
	}
}

/*
	This function hides associated <ajax:waiting> tags and displays associated
	<ajax:error> tags when an async getxml or postxml tag is finished and has
	experienced an error attempting to load the data. The tags are associated
	with a matching asyncid.
*/
function cxajax_displayError(asyncid)
{
	var		divs = getElementsByClassName("cxajax_error_" + asyncid, "div", document);
	for (var i = 0; i < divs.length; i++)
	{
		divs[i].style.display = "block";
	}
	divs = getElementsByClassName("cxajax_waiting_" + asyncid, "div", document);
	for (var i = 0; i < divs.length; i++)
	{
		divs[i].style.display = "none";
	}
}

/*
	This function hides associated <ajax:waiting> tags and displays associated
	<ajax:block> tags when an async getxml or postxml tag is finished and has
	successfully loaded the data. The tags are associated with a matching asyncid.
*/
function cxajax_displayResponse(asyncid)
{
	
	var		divs = getElementsByClassName("cxajax_response_" + asyncid, "div", document);
	for (var i = 0; i < divs.length; i++)
	{
		divs[i].style.display = "block";
		var		elems = getElementsByClassName("cxajax_js", "script", divs[i]);
		for (var i = 0; i < elems.length; i++)
		{
			var		script = elems[i];
			var		span = document.createElement("span");
			span.innerHTML = new Function(script.innerHTML)();
			script.parentNode.replaceChild(span, script);
		}
	}
	divs = getElementsByClassName("cxajax_waiting_" + asyncid, "div", document);
	for (var i = 0; i < divs.length; i++)
	{
		divs[i].style.display = "none";
	}
}

/*
	This function extracts the XPath expression from within a select attribute.
	
	The format of the select attribute is: $jsvar/xpath_expression
	Example:	$mydoc/messages/message[3], where "messages/mesage[3]" is the XPath.
	
	This supports javascript variables (preceeded by a "$" char) embedded in the
	XPath expression. These javascript variables are evaluated at run-time.
	Example:	$mydoc/messages/message[position() <= $endIndex], where "endIndex"
				is a javascript variable.
*/
function cxajax_getXPathExpr(select)
{
	var			xPathExpr = '';
	var			slashIndex = select.indexOf('/');
	if (slashIndex < 0)
	{
		xPathExpr = '.';
	}
	else
	{
		var			curIndex = slashIndex + 1;
		var			markIndex = curIndex;
		var			inVarName = false;
		while (curIndex <= select.length)
		{
			var			c = (curIndex < select.length) ? select.charAt(curIndex) : -1;
			if (inVarName)
			{
				// search for end of varName
				if (c == -1 || (! (c >= 'a' && c <= 'z') && ! (c >= 'A' && c <= 'Z') && ! (c >= '0' && c <= '9') && ! (c == '_')))
				{
					if (markIndex < curIndex)
					{
						// varName is complete -- evaluate it
						xPathExpr += eval(select.substring(markIndex, curIndex));
						markIndex = curIndex;
					}
					inVarName = false;
				}
			}
			else
			{
				// search for end of non-varName
				if (c == -1 || c == '$')
				{
					if (markIndex < curIndex)
					{
						// non-varName is complete -- grab it
						xPathExpr += select.substring(markIndex, curIndex);
						markIndex = curIndex + 1;	// skip '$' char
					}
					inVarName = true;
				}
			}
			curIndex++;
		}
	}
	return xPathExpr;
}

/*
	This function defines a javascript object containing the current iteration
	status of an associated <ajax:forEach> loop.
*/
function cxajax_loopStatus(items, begin, end, step)
{
	var			m_items = items;
	var			m_begin = (begin != null && begin != "") ? parseInt(begin) : 0;
	var			m_end = (end != null && end != "") ? parseInt(end) : m_items.length;
	var			m_step = (step != null && step != "") ? parseInt(step) : 1;
	if (m_begin < 0)
	{
		m_begin = 0;
	}
	if (m_end >= m_items.length)
	{
		m_end = m_items.length;
	}
	if (m_step < 1)
	{
		m_step = 1;
	}
	var			m_index = m_begin;
	
	/* This function advances the index -- this should only be called from within the <ajax:forEach> tag code. */
	this._advanceIndex = function()
	{
		m_index += m_step;
	}
	
	/* This function returns the current item in the iteration. */
	this.getCurrent = function()
	{
		return m_items[m_index];
	}
	
	/* This function returns the current zero-based loop index. */
	this.getIndex = function()
	{
		return m_index;
	}
	
	/* This function returns the current one-based loop index. */
	this.getCount = function()
	{
		return m_index + 1;
	}
	
	/* This function returns true, if the curent iteration is the first iteration. */
	this.isFirst = function()
	{
		return (m_index == m_begin);
	}
	
	/* This function returns true, if the curent iteration is the last iteration. */
	this.isLast = function()
	{
		return (m_index + m_step > m_end);
	}
	
	/* This function returns the value of the begin index of the iteration. */
	this.getBegin = function()
	{
		return m_begin;
	}
	
	/* This function returns the value of the end index of the iteration. */
	this.getEnd = function()
	{
		return m_end;
	}
	
	/* This function returns the value of the step increment of the iteration. */
	this.getStep = function()
	{
		return m_step;
	}
}

