/*
 * Ce module contient les fonctions JavaScript permettant de trouver des
 * élément HTML selon les ID/nom, tag ou classes.
 */

/**
 * Cette class permet de parcourir le document pour trouver les elements
 * avec class="<className>".
 */
function ElementWithClassWalker( className) {
    this.searchClass= new RegExp("(^| )"+className+"( |$)");
    this.elementList= new Array();

    this.lookAt= function ( element) {
        if ( element.className && element.className.match( this.searchClass)) {
            this.elementList.push( element);
        }
    }

    this.getElementList= function () {
        return( this.elementList);
    }
}

/**
 * Cette fonction permet d'obtenir la liste des éléments auxquels la classe
 * <code>className</code> est associé.
 * @param className Le nom de la classe pour laquelle on cherche les éléments
 *      associés.
 * @return Array des éléments trouvés.
 */
function findElementsForClass( element, className)
{
    if ( ! element || ! className) return;
    var newWalker= new ElementWithClassWalker(className);
    walkElements( element, newWalker);
    var elementList= newWalker.getElementList();
    return( elementList);
}

function findElementsForClassFromId( idOfRootElement, className) {
    if ( !idOfRootElement || ! className) return;
		
    var rootElement= findElementForId( idOfRootElement);

    var elementList= findElementsForClass( rootElement, className);

    return( elementList);
}

/**
 * Cette fonction permet d'obtenir la liste des éléments avec <code>tagName</code>.
 * @param tagName Le nom du tag recherché.
 * @return Array des éléments trouvés.
 */
function findElements( tagName) {
}

/**
 * Cette methode permet de parcourir l'arbre d'un document. Pour chaque element,
 * la methode "lookAt" de l'objet "walker" est appelee avec l'element courant.
 * La methode "lookAt" est appele sur l'element parent avant les elements enfants.
 */
function walkElements( startElement, walker) {
    if ( !startElement || !startElement.nodeType) {
        throw new Error("walkElement: Le parametre startElement n'est pas un element valide.");
    }
    if ( typeof( walker) != 'object' || typeof( walker.lookAt) != 'function') {
        throw new Error("walkElement: Le parametre walker doit contenir une fonction 'lookAt'.");
    }
    if ( !startElement.firstChild) {
        return;
    }
    var hierarchy= new Array();
    var child= standardElement(startElement.firstChild);

    do {
        while( child != null) {
            walker.lookAt( child);

            if ( child.nodeType && child.firstChild) {
                hierarchy.push( child);
                child= standardElement(child.firstChild);
            } else {
                child= standardElement(child.nextSibling);
            }
        }

        while ( child==null && hierarchy.length > 0) {
            child= hierarchy.pop();
            child= standardElement(child.nextSibling);
        }
    } while( child!=null);
}


/**
 * Cette fonction permet d'obtenir l'élément avec <code>idElement</code>.
 * @param idElement L'id (ou le nom) recherché.
 * @return {obj,style} L'élément trouvé.
 */
function findElementForId( idElement) {
    if ( !idElement) return;

    var elementFound= null;

    if (document.getElementById) {
        elementFound= document.getElementById(idElement);
    } else if (document.all) {
        elementFound= document.all[idElement];
    } else if (document.layers) {
        elementFound= document.layers[idElement];
    }

    return standardElement( elementFound);
}

/**
 * Permet de créer une représentation d'un élément qui est indépendante du 
 * fureteur.
 * Crée l'attribut crgl.style pour contenir le style associé à l'element
 */
function standardElement( object) {

    if ( object && object != null && object.nodeType && object.nodeType!=3) {
        if ( ! object.crgl) {
            object.crgl= new Object();
        }
    		
        if (document.getElementById || document.all) {
            object.crgl.style= object.style;
        } else if (document.layers) {
            object.crgl.style= object;
        }
    }

    return object;
}
