//----------------------------------------------------------------------------
// cbEvent.js
//    some support for event handlers ...
//----------------------------------------------------------------------------

// object prototype
function xEvent( evt ) {
  var e = evt || window.event;
  if ( e ) {
    this.type          = e.type;
    this.target        = e.target || e.srcElement;
    this.relatedTarget = e.relatedTarget;

    /*@cc_on
    if ( e.type == 'mouseover' ) this.relatedTarget = e.fromElement;
    if ( e.type == 'mouseout'  ) this.relatedTarget = e.toElement;
    @*/

    this.pageX   = isDef( e.pageX   ) ? e.pageX
                 : isDef( e.clientX ) ? e.clientX + xScrollLeft( )
                 :                      null;
    this.pageY   = isDef( e.pageY   ) ? e.pageY
                 : isDef( e.clientY ) ? e.clientY + xScrollTop( )
                 :                      null;
    this.offsetX = isDef( e.offsetX ) ? e.offsetX
                 : isDef( e.layerX  ) ? e.layerX
                 : this.offsetX       ? this.pageX - xPageX( this.target )
                 :                      null;
    this.offsetY = isDef( e.offsetY ) ? e.offsetY
                 : isDef( e.layerY  ) ? e.layerY
                 : this.offsetY       ? this.pageY - xPageY( this.target )
                 :                      null;

    this.getTargetWithProperty
      = function( prop ) {
        var el = this.target;
        while ( typeof( el[prop] ) == 'undefined' ) {
          if ( el == window ) return null;
          el = el.parentNode;
        }
        return el;
      };

    this.keyCode  = e.keyCode || e.which || 0;
    this.shiftKey = e.shiftKey;
    this.ctrlKey  = e.ctrlKey;
    this.altKey   = e.altKey;

    if ( typeof e.type == 'string' ) {
      if      ( e.type.indexOf( 'click' ) != -1 ) {
        this.button = 0;
      }
      else if ( e.type.indexOf( 'mouse' ) != -1 ) {
        this.button = e.button;

        /*@cc_on
        if      ( e.button & 1 ) this.button = 0;
        else if ( e.button & 4 ) this.button = 1;
        else if ( e.button & 2 ) this.button = 2;
        @*/
      }
    }
  }
}

//
//  e   string or object reference.
//  eT  event type: 'mousemove', 'click', 'resize', etc.
//  eL  event listener function.
//  cap boolean capture event flag.
//

function xAddEventListener( e, eT, eL, cap ) {
  if ( ( e = xGetElementById( e ) ) != null ) {
    eT = eT.toLowerCase( );
    if ( e.addEventListener )
      e.addEventListener( eT, eL, cap || false );
    else if ( e.attachEvent )
      e.attachEvent( 'on' + eT, eL );
    else {
      var o = e[ 'on' + eT ];
      e[ 'on' + eT ]
        = typeof o == 'function' ? function( v ) { o(v); eL(v); }
        :                          eL;
    }
  }
}

function xAddEventListenerPrepended( e, eT, eL, cap ) {
  if ( ( e = xGetElementById( e ) ) != null ) {
    eT = eT.toLowerCase( );
    var o = e[ 'on' + eT ];
    e[ 'on' + eT ]
      = typeof o == 'function' ? function( v ) { return( eL(v) && o(v) ); }
      :                          eL;
  }
}

function xAddEventListenerAppended( e, eT, eL, cap ) {
  if ( ( e = xGetElementById( e ) ) != null ) {
    eT = eT.toLowerCase( );
    var o = e[ 'on' + eT ];
    e[ 'on' + eT ]
      = typeof o == 'function' ? function( v ) { o(v); return( eL(v) ); }
      :                          eL;
  }
}

function xRemoveEventListener( e, eT, eL, cap ) {
  if ( ( e = xGetElementById( e ) ) != null ) {
    eT = eT.toLowerCase( );
    if ( e.removeEventListener)
      e.removeEventListener( eT, eL, cap || false );
    else if ( e.detachEvent )
      e.detachEvent( 'on' + eT, eL );
    else
      e[ 'on' + eT ] = null;
  }
}

function xStopPropagation( evt ) {
  if ( evt && evt.stopPropagation )
    evt.stopPropagation( );
  else if ( window.event )
    window.event.cancelBubble = true;
}

function xPreventDefault( evt ) {
  if ( evt && evt.preventDefault )
    evt.preventDefault();
  else if ( window.event )
    window.event.returnValue = false;
}


function xEnableDrag( id, fS, fD, fE ) {
  var mx = 0, my = 0, el = xGetElementById( id );
  if ( el ) {
    el.xDragEnabled = true;
    xAddEventListener( el, 'mousedown', dragStart, false );
  }
  // Private Functions
  function dragStart( e ) {
    if ( el.xDragEnabled ) {
      var ev = new xEvent( e );
      xPreventDefault( e );
      mx = ev.pageX;
      my = ev.pageY;
      xAddEventListener( document, 'mousemove',  drag, false );
      xAddEventListener( document, 'mouseup', dragEnd, false );
      if ( fS ) {
        fS( el, ev.pageX, ev.pageY, ev );
      }
    }
  }

  function drag( e ) {
    var ev, dx, dy;
    xPreventDefault( e );
    ev = new xEvent( e );
    dx = ev.pageX - mx;
    dy = ev.pageY - my;
    mx = ev.pageX;
    my = ev.pageY;
    if ( fD ) {
      fD( el, dx, dy, ev );
    }
    else {
      xMoveTo( el, el.offsetLeft + dx, el.offsetTop + dy );
    }
  }

  function dragEnd( e ) {
    var ev = new xEvent( e );
    xPreventDefault( e );
    xRemoveEventListener( document, 'mouseup', dragEnd, false );
    xRemoveEventListener( document, 'mousemove',  drag, false );
    if ( fE ) {
      fE( el, ev.pageX, ev.pageY, ev );
    }
    if ( xEnableDrag.drop ) {
      xEnableDrag.drop( el, ev );
    }
  }
}

xEnableDrag.drops = [ ]; // static property

function xDisableDrag( id ) {
  xGetElementById( id ).xDragEnabled = false;
}
