/**
* Chained event handler system.
*
* Enables a series of callbacks, possibly asynchronously, to be
* called from an onClick or similar event handler. This assumes
* that callbacks get a reference to the element invoking the event
* and that they call fv_continueChain( elem ) from within their own
* callback handler.
*
* Copyright DTLink, LLC 2008.
*/

// var ddt = new DDT();
// ddt._ddtOn();

// guard against multiple inclusions

if ( typeof( fv_addJSChainHandler ) == 'undefined' )
	{

// ------------------------------------------

/**
* add an event handler to the current chain.
*/

function fv_addJSChainHandler( elem, position, func )
{

// ddt._ddt( "fv_jsChain.js", "24", "fv_addJSChainHandler(): TOP: type of this is '" + typeof( elem ) + "' tag is '" + elem.tagName + "' func in '" + func + "'" );

if ( typeof ( elem.fv_eventHandlerChain ) == 'undefined' )
	elem.fv_eventHandlerChain = new Array();

// prevent against adding the same callback twice. This assumes the position value
// is incremented for each call to addJSChainHandler.

if ( typeof( elem.fv_eventHandlerChain[ position ] ) != 'undefined' )
	{
	// ddt._ddt( "fv_jsChain.js", "36", "fv_addJSChainHandler(): func '" + func + "' already defined" );
	return;
	}

// ddt._ddt( "fv_jsChain.js", "44", "fv_addJSChainHandler(): func '" + func + "' was not in the chain. adding" );

elem.fv_eventHandlerChain.push( func );

return false;
}
							  
// ----------------------------------
// fire off the chain.

function fv_runJSChain( elem )
{

// ddt._ddt( "fv_jsChain.js", "57", "fv_runChain(): Starting chain" );

elem.fv_eventHandlerChainPosition = 0;

return fv_continueJSChain( elem );

}

// -------------------------------------
// used to continue a chain in progress.

function fv_continueJSChain( elem )
{

// ddt._ddt( "fv_ujsChain.js", "22", "fv_continueJSChain(): # of chainHandlers " + elem.fv_eventHandlerChain.length + "' position '" + elem.fv_eventHandlerChainPosition + "'" );

while ( callback = elem.fv_eventHandlerChain[ elem.fv_eventHandlerChainPosition ] )
	{

	elem.fv_eventHandlerChainPosition++;

	// ddt._ddt( "fv_jsChain.js", "59", "fv_continueJSChain(): calling next chained callback '" + callback + "'" );

	if ( callback( elem ) == false )
		{
		// ddt._ddt( "fv_jsChain.js","42", "fv_continueJSChain(): callback returned false, returning out of runJSChain." );
		// ddt._ddt( "fv_jsChain.js", "43", "fv_continueJSChain() : callback is '" + callback + "'" );

		return false;
		}
	else
		{
		// ddt._ddt( "fv_Chain.js", "47", "fv_continueChain(): callback returned true, continuing loop in runChain." );
		}

	}

// ddt._ddt( "fv_jsChain.js", "73", "fv_continueChain(): Bottom of chain. exiting with true." );

return true;

}

}	// end

