/**
 * Copyright (c) 2006, Eric Malone (http://em.hopto.org)
 * All rights reserved.
 *
 * -- License Information --
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright 
 *     notice, this list of conditions and the following disclaimer in the 
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Eric Malone nor the names of additional 
 *     contributors may be used to endorse or promote products derived from 
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @todo javacript cookie support detection
 *
 */


// cross-browser event handling
window.addEvent = function( target, type, listener, use_capt )
{
  if( target.addEventListener )
    return target.addEventListener( type, listener, use_capt );
  else if( target.attachEvent )
    return target.attachEvent( 'on' + type, listener );
  else
    target[ 'on' + type ] = listener;
}

window.removeEvent = function( target, type, listener, use_capt )
{
  if( target.removeEventListener )
    return target.removeEventListener( type, listener, use_capt );
  else if( target.detachEvent )
    return target.detachEvent( 'on' + type, listener );
  else
    target[ 'on' + type ] = null;
}

/**
 * for elem, returns object for offsets { posX, posY, height, width }
 */
window.getXY = function( elem )
{
  if( typeof( elem.offsetLeft ) != 'number' )
    return null;
  
  var pos = { posX : elem.offsetLeft, 
              posY : elem.offsetTop,
              width  : elem.offsetWidth,
              height : elem.offsetHeight
            };
  if( elem.offsetParent )
  {
    var par = getXY( elem.offsetParent );
    if( par != null )
    {  
      pos.posX += par.posX; 
      pos.posY += par.posY;
    }
  }

  return pos;
}

window.debugObj = function( obj, popup )
{
  var out ='';
  var error = false;
  try
  {
    for( var i in obj )
    {
      out += i + ": " + obj[ i ] + ( popup ? "<br>" : "\n" );
      
    }
  } catch( e ) { error = true; }
  
  if( error ) out += ( popup ? "<br><br>" : "\n\n" ) + 'an error occurred during iteration';
  
  if( popup )
  {
    var win = window.open( '', '', '' );
    win.document.write( out );
  }
  else
    alert( out );
}

/**
 * @todo check to see if iframe capable, if iframe compatability can be implemented
 */
window.ajaxEnabled = function()
{
  if( window.XMLHttpRequest )
    return true;
  else if( window.ActiveXObject )
  {
    var req_types = [ 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP' ];
    for( var i=0; i<req_types.length; ++i )
    {
      try {
        var xmlrequest = new ActiveXObject( req_types[i] );
        return true;
      } catch( e ) {}
    }
  }
  else
    return false;
}

/**
 * Takes event and condenses the different attributes/functions into a single
 * Event API
 *
 * @return object The final event
 * properties
 * + event  => The actual event object
 * + target => Target of the event
 * 
 * methods
 * + stopPropagation => stop propagating the event. Will only cancel the
 * bubbling phase if in IE
 * + preventDefault  => prevent the default action from occurring on the target   
 */
window.getEvent = function( e )
{
  var ev = {};
  ev.event = e ? e : ( window.event ? window.event : null );
  if( ev.event.target )
    ev.target = ev.event.target;
  else if( ev.event.srcElement )
    ev.target = ev.event.srcElement;
  else
    ev.target = null;

  ev.preventDefault = ev.event.preventDefault ? function() { ev.event.preventDefault(); } : 
    ( window.isMSIE ? function() { ev.event.returnValue = false; } : null );

  ev.stopPropagation = ev.event.stopPropagation ? function() { ev.event.stopPropagation(); }: 
    ( typeof( ev.event.cancelBubble ) != 'undefined' ? function() { ev.event.cacelBubble = true; } : null );
    
  return ev;
}

/**
 * Recursively set handlers for nested elements. Meant for events that will not
 * bubble up to the parent.
 *
 * @param elem The parent node
 * @param handlers object containing the handler functions
 *        { 'mouseover' : function() { } [, event type : function ], [] }
 */
function addHandlers( elem, handlers )
{
  for( var i in handlers )
  {
    addEvent( elem, i, handlers[ i ], false );
  }

  if( !elem.hasChildNodes() )
    return;
  
  for( var j=0; j<elem.childNodes.length; ++j )
  {
    if( elem.childNodes[ j ].nodeType == 1 )
    {
      addHandlers( elem.childNodes[ j ], handlers );
    }
  }
}

/**
 * basic browser detection, may need revision and addition of safari check
 */
window.isMSIE  = window.clientInformation ? true : false;
window.isOpera = window.opera ? true : false;
window.isGecko = window.scrollbars ? true : false;

// Array push function to account for older IE browsers
if( !Array.prototype.push )
  Array.prototype.push = function( val ) { this[ this.length ] = val; };

window.DOMEnabled = typeof( window.document.createElement ) != 'undefined' ? true : false;
