/*
 * Ce javascript sert a detacher l'assignation d'une fonction a executer
 * de l'attribut "on..." des balise HTML.
 * Compatibilite:
 *  IE 6.0.2800.1106 (Q903235) (*****)
 *  Firefox 1.0.6
 *  Safari 1.3 (v312)
 *  Netscape 7.2
 */

Array.prototype.indexOf= indexOf;

function indexOf( obj) {
	var retValue= -1;
	if ( obj != null) {
		for( var i= 0; retValue==-1 && i < this.length; i++) {
			if ( this[i]==obj) {
				retValue= i;
			}
		}
	}
	return( retValue);
}

/*
 * <p>EventManager sert a l'enregistrement de fonction devant être execute sur
 * certains evenement survenant sur certains elements.</p>
 * <p>Pour ajouter la fonction pageOuverte lors du "onload" de la fenetre:</p>
 * <code>
 *  EventManager.registerEvent( window, 'load', pageOuverte);
 * </code>
 * <p>La fonction "pageOuverte" recoit un parametre qui est l'evenement. Pour
 *  permettre l'utilisation de cette librairie sur plusieurs fureteur, les
 *  attributs suivants sont ajoute a l'evenement:</p>
 * <ul>
 *  <li>crglTarget: L'element ayant >>recu<< l'evenement (pas necessairement 
 *      celui qui traite l'evenement). Equivalent a 'target' sur Firefox et 
 *      'srcElement' sur IE.</li>
 *  <li>docPosX: La position en X de la souris dans le document. [opt]</li>
 *  <li>docPosY: La position en Y de la souris dans le document. [opt]</li>
 * </ul>
 * 
 */
var EventManager= new function () {
    var debug= false;
		
    /**
     * Cette fonction permet d'obtenir la liste des fonctions enregistre pour
     * un element et un evenement.
     * @param element L'element pour lequel on veut obtenir la liste des fonctions
     *      enregistrees pour l'evenement 'event'.
     * @param event L'evenement pour lequel on veut obtenir la liste des fonctions
     *      enregistrees.
     * @return Un tableau de fonction.
     */
    this.getEventsFor= function ( element, event) {
        if ( ! element.crglEvents ) {
            element.crglEvents= new Object();
        }
        if ( ! element.crglEvents[event]) {
            element.crglEvents[event]= new Array();
        }
        return( element.crglEvents[event]);
    }

    /**
     * Cette fonction est appelee lorsqu'un evenement, pour lequel une ou plusieurs
     * fonctions sont enregistre, est lance.
     */
    this.fireEvent= function (element, e) {

        if ( EventManager.debug) alert( "fireEvent: appele");
        // Creer un objet representant (de facon uniforme) l'objet evenement recu.
        var comCrglEvent= (!e ? window.event : e);
        comCrglEvent.crgl= new Object();
				
	if ( EventManager.debug) alert( "fireEvent: " + comCrglEvent.type);
        if (comCrglEvent.target) {
            if ( EventManager.debug) alert( "fireEvent: target");
            comCrglEvent.crgl.target= comCrglEvent.target;
        }
        else if (comCrglEvent.srcElement) {
            if ( EventManager.debug) alert( "fireEvent: srcElement");
            comCrglEvent.crgl.target= comCrglEvent.srcElement;
        }
        else {
            if ( EventManager.debug) alert( "fireEvent: this : " + this);
            comCrglEvent.crgl.target= this; // this c'est l'element qui a appele cette fonction
        }
	  
        comCrglEvent.crgl.element= element;

	if ( EventManager.debug) alert( "fireEvent: " + comCrglEvent.crgl.target);
        if (comCrglEvent.crgl.target.nodeType == 3) // defeat Safari bug
            comCrglEvent.crgl.target= comCrglEvent.crgl.target.parentNode;

        // Position
        if (comCrglEvent.pageX || comCrglEvent.pageY) {
            comCrglEvent.crgl.posx = comCrglEvent.pageX;
            comCrglEvent.crgl.posy = comCrglEvent.pageY;
	} else if (comCrglEvent.clientX || comCrglEvent.clientY) {
            comCrglEvent.crgl.posx = comCrglEvent.clientX + document.body.scrollLeft;
            comCrglEvent.crgl.posy = comCrglEvent.clientY + document.body.scrollTop;
	}
	
        // Appeler toutes les fonctions enregistrer pour cet evenement pour 
        // la cible.
	if ( EventManager.debug) alert( "fireEvent: getEventsFor");
        var fcts= EventManager.getEventsFor( element, comCrglEvent.type);
        var retValue;
	if ( EventManager.debug) alert( "fireEvent: getEventsFor #"+fcts.length);
        for( var i= 0; i < fcts.length; i++) {
          if ( EventManager.debug) alert( "fireEvent: call function "+fcts[i]);
            retValue= fcts[i]( comCrglEvent);
            if ( typeof(retValue) != 'undefined' && !retValue) {
                return false;
            }
        }

        return( retValue);
    }
	
    /**
     * <p>Enregistre un nouvelle evenement (event) pour l'element (element).</p>
     * <p>La fonction est enregistre à la suite de celle deja enregistre.</p>
     * <p>Si une fonction est deja enregistree (ou est enregistre ulterieurement) a 
     * 	l'element sans faire appel a l'EventManager , alors l'EventManager ne sera jamais 
     *  appele pour l'evement sur l'element. Et par consequent aucune des méthodes 
     * 	enregistre a l'EventManager ne sera appele.</p>
     * @param element L'element sur lequel on veut enregistre une nouvelle fonction
     *  pour l'evenement 'event'.
     * @param event L'evenement pour lequel on veut ajouter une fonction.
     * @param fct La fonction a ajouter pour l'evenement 'event' sur l'element.
     */
    this.registerEvent= function ( elementCible, event, fct) {
        if ( EventManager.debug) alert( elementCible + " : " + event + " : " + fct);
        if ( typeof( fct) != 'function') {
            throw new Error("registerEvent: Le parametre fct doit etre une fonction");
        }
        if ( EventManager.debug) alert( "On continue");

        // Obtient la liste des fonctions appeles sur l'event de l'element.
        var elementEvent= EventManager.getEventsFor( elementCible, event);
        if ( EventManager.debug) alert( "On ajoute la fonction a la liste.");

        // Ajouter la fonction 
        elementEvent.push( fct);

        // On enregistre l'evenement sur l'element, s'il n'est pas deja enregistre.
        if ( EventManager.debug) alert( "On ajoute l'evenement ("+elementCible['on'+event]+")");
        if ( ! elementCible['on'+event]) {
            elementCible['on'+event]= function (e) {
                EventManager.fireEvent(elementCible, e);
            };
        }

    }
	
    /**
     * Enregistre une fonction en reponse a un evenement a la position specifie.
     * Si la position specifie est plus grande que le nombre de fonction deja
     * enregistre, elle est ajoute a la fin.
     */
    this.registerEventAt= function (element, event, fct, position) {
            throw new Error( "registerEventAt: Non implemente");
    }

    /**
     * Enregistre une fonction en reponse a un evenement apres la fonction (afterFunction).
     * Si la fonction (afterFunction) n'est pas deja enregistre, la nouvelle fonction n'est
     * pas enregistre.
     */
    this.registerEventAfter= function (element, event, fct, afterFunction) {
            throw new Error( "registerEventAfter: Non implemente");
    }

    /**
     * Retire de la liste de fonctions deja enregistre la fonction specifie.
     * La fonction est retire une seule fois. Donc, si la meme fonction a ete
     * enregistre plusieurs fois, unregisterEvent doit etre appele autant de fois.
     */
    this.unregisterEvent= function (element, event, fct) {
    	var fcts= EventManager.getEventsFor(element, event);
    	if ( fcts && fcts.length) {
            var fctIdx= fcts.indexOf( fct);
            if ( fctIdx >= 0) {
                fcts.splice(fctIdx,1);
            }
    	}
    }

    /**
     * Cette methode permet de savoir si une fonction a deja ete enregistre pour
     * un evenement sur un element.
     */
    this.isEventRegistered= function (element, event, fct) {
        var fctIdx= -1;
    	var fcts= EventManager.getEventsFor(element, event);
    	if ( fcts && fcts.length) {
            fctIdx= fcts.indexOf( fct);
        }
        return ( fctIdx >= 0);
    }
		
    /**
     */
    this.about= function () {
        return("EventManager v1.0");
    }
}

