/****************
 * jQuery.fn.menuActif()
 *
 * Francois Moreau, grillonbleu@gmail.com, mai-juillet 2009
 *
 * Dans un menu, demarque un lien comme actif.
 * Le lien est considere comme actif si :
 *  - son href pointe vers la page courante ;
 *  - son href équivaut au href d'une balise link[rel=section] existante ;
 *  - son contenu textuel existe dans la balise title.
 * La demarcation comprend :
 *  - attribution d'une classe au lien de page ;
 *  - attribution d'une classe au lien de section ;
 *  - visibilite forcee de tous les liens de la section.
 *
 *
 * PARAMETRES (valeurs par defaut)
 * classeActif ('on')
 *    Classe donnee au lien de page et de section active.
 * requeteLiensSections ('> div > a[href]')
 *    Requete jQuery qui trouve tous les liens de sections,
 *    dans le contexte du menu.
 * trouvePagesParSection (function(element_jQuery) return element_jQuery)
 *    Fonction qui, a partir de l'element jQuery du lien de section,
 *    trouve les liens de pages de la section.
 *
 * USAGE :
 *  jQuery("#menu").menuActif({option1: val1, option2: val2});
 *  Voir tests.html pour exemples.
 *  Avec firebug, la raison pour laquelle le lien a ete active est affichee dans la console.
 * 
 * DETAILS :
 *  Un seul lien peut etre considere comme actif, le premier trouve, dans l'ordre ou il apparait dans la page.
 *
 *  menuActif procede en "cascade" :
 *   - Il parcourt tous les liens a la recherche d'un lien qui pointe vers la page courante ;
 *     - Des qu'il en trouve un, il s'arrete est l'active.
 *     - Sinon, il continue.
 *   - Il parcourt tous les liens a la recherche d'un lien qui pointe vers la meme page que link[rel=section] ;
 *     - Des qu'il en trouve un, il s'arrete est l'active.
 *     - Sinon, il continue.
 *   - Il parcourt tous les liens a la recherche d'un lien dont le texte existe dans title ;
 *     - Des qu'il en trouve un, il s'arrete est l'active.
 */

jQuery.fn.menuActif = function(options) {
    var opts = jQuery.extend({}, jQuery.fn.menuActif.defaults, options);

    //FONCTIONS


    //Affichage d'info concernant l'execution dans firebug, si disponible.
    var console = function() {};
    if("console" in window &&
       "log"     in window.console &&
       "function" == typeof window.console.log) {
        var console = function (message) {
            window.console.log("menu_actif.js : " + message);
        }
    }


    //Fonction qui parcourt tous les liens du menu.
    //Des qu'il en trouve un qui soit approprie, il l'active et le retourne.
    //Le parametre fn_est_actif determine la condition.
    function trouveLienActif(menu, fn_est_actif) {
        var liens_sections = menu.find(opts.requeteLiensSections);
        for(var ii=0; ii<liens_sections.length; ++ii) {
            var lien_section = liens_sections.eq(ii);

            var liens_pages         = opts.trouvePagesParSection(lien_section);
            var liens_pages_actives = liens_pages.filter(function() {return fn_est_actif(this);})
                                                 .addClass(opts.classeActif);

            var lien_actif;
            if(liens_pages_actives.length) {
                lien_actif = liens_pages_actives.eq(0);
            }
            if(fn_est_actif(lien_section[0])) {
                lien_actif = lien_section.eq(0);
            }

            if(undefined !== lien_actif) {
                afficheSectionPages(this, liens_pages);
                lien_section.addClass(opts.classeActif);
                return lien_actif;
            }
        }
        return false;
    }


    //Forcer la visibilite de la section du lien de page
    function afficheSectionPages(menu, lien_pages) {
        var parents = lien_pages.parents();
        for(var kk=0; kk<parents.length; ++kk) {
            if(menu === parents[kk]) break;
            parents.eq(kk).show();
        }
    }


    //FONCTIONS DE VERIFICATION : UN LIEN EST-IL A ACTIVE?
    
    function lienPointePageCourante(lien) {
        return lien.href == location.href;
    }

    function lienPointeLinkSection(lien) {
        var link_section = jQuery("link[rel=section]");
        return link_section.length && lien.href == link_section[0].href;
    }

    function lienTexteDansTitre(lien) {
        var texte_lien  = jQuery(lien).text();
        var texte_titre = document.title;
        return -1 != texte_titre.indexOf(texte_lien);
    } 


    //CORPS DE L'APPEL DE PLUGIN
    return this.each(function() {
        var menu = jQuery(this);

        //Recherche du lien actif
        var lien_active;
        if(lien_active = trouveLienActif(menu, lienPointePageCourante)) {
            console("lien activé : [" + 
                    lien_active.attr("href") + 
                    "] correspond à la page courante");
        } else if(lien_active = trouveLienActif(menu, lienPointeLinkSection)) {
            console("lien activé : [" +
                    lien_active.attr("href") +
                    "] correspond au link[rel=section]");
        } else if(lien_active = trouveLienActif(menu, lienTexteDansTitre)) {
            console("lien activé : le texte [" +
                    lien_active.text() +
                    "] existe dans le title [" +
                    jQuery("title").text() + "]");
        } else {
            var nb_liens = 0;
            var compte_liens = function() {++nb_liens;};
            trouveLienActif(menu, compte_liens);
            console("Aucun lien activé. " + nb_liens + " liens parcourus");
        }
    });

};
jQuery.fn.menuActif.defaults = {
    classeActif: 'on',
    requeteLiensSections: '> div > a[href]',
    trouvePagesParSection: function(lien_section) {
        return lien_section.parent('div').next('ul').find('li > a[href]');
    }
};


//Appel

jQuery(function() {
    jQuery('#menu').menuActif();
});

// FIN jQuery.fn.menuActif()
