function addListener( objet, eventName, eventHandler ) {
  var ActiveBubbling = ( arguments.length > 3 )
    ? arguments[ 3 ] : false;
  if ( objet.addEventListener ) objet.addEventListener( eventName, eventHandler, ActiveBubbling );
  else if ( objet.attachEvent ) objet.attachEvent( 'on' + eventName, eventHandler );
  else {
    var oldHandler = null;
    eval( 'if ( objet.on' + eventName + ' ) oldHandler = objet.on' + eventName + '; objet.on' + eventName + ' = function() { if ( oldHandler != null ) oldHandler(); eventHandler() };' );
  }
}

function Delegate( obj, methodName ) {
  this.target = obj;
  this.method = methodName;

  this.execute = function() {
    var tmpArray = new Array();
    for( var i=0; i<arguments.length; i++ )
      tmpArray.push( arguments[ i ] );
    this.target[ this.method ].apply( this.target, tmpArray );
  }
}
/*
  function objet() { this.ok = function( context ) { temp( context ); } }

  function statique() { }
  statique.ok = function( context ) { temp( context ); }

  function temp( context ) { alert( context ); }

  //
  oLog.addListener( 'onSpecificEvent', temp );

  // ou
  oLog.addListener( 'onSpecificEvent', statique.ok );

  // ou
  var objTemp = new objet();
  oLog.addListener( 'onSpecificEvent', objTemp.ok );
*/
function Listenable() {
  /**
    @private
    @brief  Collection des écouteurs
  */
  this.listeners = new Array();

  /**
    @brief  Attache un écouteur à un évènement précis
    @param  eventName string    le nom de l'évènement auquel on attache notre fonction callback
    @param  callback  function  une fonction/méthode à appeler lorsque l'évènement sera lancé
  */
  this.addListener = function( eventName, callback ) {
    this.listeners.push( new Array( eventName, callback ) );
  }
  /**
    @brief  Cette méthode sert principalement pour des appels via setTimeout ou setInterval
    @param  obj   object  un objet
    @param  meth  string  le nom de la méthode de l'objet que l'on souhaite appeler
    @return function
  */
  this.callback = function( obj, meth ) {
    var args = new Array();
    if ( arguments.length > 2 )
      for( var i=2; i<arguments.length; i++ )
        args.push( arguments[ i ] );
    return function() {
      obj[ meth ]( args );
    }
  }
  /**
    @brief  Notifie les objets écouteurs que l'évènement eventName a été lancé
    @param  eventName string  le nom de l'évènement lancé
    @param  context   mixed   paramètre à passer lors de l'appel du callback
    @return void
  */
  this.fireEvent = function( eventName ) {
    var args = new Array();
    for( var i=1; i<arguments.length; i++ )
      args.push( arguments[ i ] );
    for( var i=0; i<this.listeners.length; i++ )
      if ( this.listeners[ i ][ 0 ] == eventName )
        if ( isInstance( this.listeners[ i ][ 1 ], Delegate ) )
          this.listeners[ i ][ 1 ].execute.apply( this.listeners[ i ][ 1 ], args );
        else
          this.listeners[ i ][ 1 ].apply( this, args );
  }
}