//***************************************************************
// events.js
//
// Include the events.js script in the head of your document;
// Register any events you want to handle by calling hookEvent, 
// passing the name of the event and the function you want called 
// when that event occurs; Write your event handlers, returning 
// true from each one to permit further processing for this event 
// by other scripts, or returning false to prevent any more 
// processing.
//***************************************************************

// Assign event handler object
var eventHandler = new eventHandlerArray( null );

// Decide what browser is running
var fNetscape = navigator.appName.indexOf( "Microsoft" ) 
             != -1 ? false : true;

// Create cross-browser compatible event structure
var xEvent = new xEventObject(fNetscape);

function xEventObject(flag)
{
    this.event = null;
    this.type = null;
    this.target = null;
    this.keyCode = null;
    this.button = null;
    this.pageX = null;
    this.pageY = null;
    this.altKey = null;
    this.ctrlKey = null;
    this.shiftKey = null;
    this.netscape = flag;
    return this;
}

function eventHandlerArray()
{
    return new Array( eventHandlerItem( null ) );
}

function eventHandlerItem( handlerID )
{
    this.funcList = new Array();
    this.hID = handlerID;
    return this;
}

//***************************************************************
//* hookEvent()
//* Arguments: 
//*   -The event to capture
//*   -The function to handle the event
//***************************************************************
function hookEvent()
{
    var theEvent = hookEvent.arguments[0];
    var theHook = hookEvent.arguments[1];
    var fDocLevel = hookEvent.arguments[2];
    
    // Capture the event at the document level.
    if ( fNetscape == true )
    {
        if ( document.captureEvents )
        {
            eval( "document.captureEvents( Event." + 
                                           theEvent.toUpperCase() + " );" );
            eval( "document.on" + theEvent.toLowerCase() + " = runEvent;" );
        }
        else return;
      }
      else
      {
        // Field event to document if it hasn't already been fielded
        if ( !eval( "document.on" + theEvent.toLowerCase() ) )
            eval( "document.on" + theEvent.toLowerCase() + " = runEvent;" );
    }

    var i;
    var j;

//    document.writeln("<p># Events: " + eventHandler.length + "</p>");

    // Locate the event in the event handlers list
    for ( i = 0; i < eventHandler.length; i++ )
    {
        if ( eventHandler[ i ].hID == theEvent )
        {
//            document.writeln("<p>Find hook: " + theHook + "</p>");

            // Located the event; find a free slot for this handler
            for ( j = 0; j < eventHandler[ i ].funcList.length; j++ ) {}

//            document.writeln("<p>Add hook: " + theHook + "</p>");

            eventHandler[ i ].funcList[ j ] = theHook;
            return;
        }
    }    
    // Event has not yet been assigned a handler, so extend event structure
    eventHandler[ i ] = new eventHandlerItem( null );
    eventHandler[ i ].hID = theEvent
    eventHandler[ i ].funcList[0] = theHook
}


//***************************************************************
//* runEvent()
//***************************************************************
function runEvent( event )
{

    // Remap NN/IE event in cross-browser Event object.
    if ( fNetscape == false )
    {
        xEvent.event = window.event;
        xEvent.type = window.event.type;
        xEvent.target = (window.event.srcElement) ? window.event.srcElement : null;
        xEvent.keyCode = (window.event.keyCode) ? window.event.keyCode : null;
        xEvent.button = (window.event.button) ? window.event.button : null;
        xEvent.altKey = (window.event.altKey) ? window.event.altKey : null;
        xEvent.ctrlKey = (window.event.ctrlKey) ? window.event.ctrlKey : null;
        xEvent.shiftKey = (window.event.shiftKey) ? window.event.shiftKey : null;
        xEvent.pageX = (window.event.clientX) ? window.event.clientX : null;
        xEvent.pageY = (window.event.clientY) ? window.event.clientY : null;
    }
    else
    {
        xEvent.event = event;
        xEvent.type = event.type;
        xEvent.target = event.target;
        xEvent.keyCode = (event.which) ? event.which : null;
        xEvent.button = (event.which) ? event.which : null;
        xEvent.altKey = (event.modifiers) ? (event.modifiers & Event.ALT_MASK) : null;
        xEvent.ctrlKey = (event.modifiers) ? (event.modifiers & Event.CTRL_MASK) : null;
        xEvent.shiftKey = (event.modifiers) ? (event.modifiers & Event.SHIFT_MASK) : null;
        xEvent.pageX = (event.pageX) ? event.pageX : null;
        xEvent.pageY = (event.pageY) ? event.pageY : null;
    }    

    var i;
    var j;
    var retCode;

    // Run the event handler list
    for ( i = 0; i < eventHandler.length; i++ )
    {
        if ( eventHandler[ i ].hID == xEvent.type )
        {
            // Found an array of handlers for this event; run each in turn
            for ( j = 0; j < eventHandler[ i ].funcList.length; j++ )
            {
                retCode = eval( eventHandler[ i ].funcList[ j ] 
                                + "( xEvent )" )
                if ( retCode == false )
                {
                    // Stop handling event, and cancel default handling too
                    if (!fNetscape)
                      window.event.cancelBubble = true;
                    return false;
                }
            }
            // Allow default handling, after we have run our events
            if (fNetscape)
              return routeEvent(event);
            else
              return true;
        }
    }

    // Won't get here
    return false;
}
