Savoir d'ou vient un statechange en js ?

Par joxs, il y a 12 ans


Bonjour à tous,

J'aurais aimé savoir comment on peut faire pour savoir de quel lien vient un statechange, je m'explique:

Dans mon projet, j'utilise le plugin ajaxify html5 et pour repérer un changement il utilise la fonction

$window.bind('statechange',function(){

qui permet de savoir si il y à un changement dans l'url, jusque là tout va bien, mais le problème c'est que en fonction du menu dans lequel l'utilisateur à cliqué, la fonction doit changer ! Est-ce possible avec une fonction du style

.click(function(){

?

Je vous remercie d'avance.

35 réponses

NotANumber, il y a 12 ans

Salut,

je vois que ajaxify utilise History.js.
Normalement, il doit y avoir une méthode getStat().url qui doit être attaché à l'objet history.
Regarde de ce coté là.

joxs, il y a 12 ans

Oui il y à bien ces deux variables :

State = History.getState();
url = State.url;

Mais elles retournent l'url et non pas le bouton sur lequel on à cliqué !

Merci pour cette réponse (hyper) rapide NotANumber :)

NotANumber, il y a 12 ans

Pas de soucis, ;)
Si je comprends bien, tu voudrais appeler une méthode différente pour chaque boutons de ton menu ?

joxs, il y a 12 ans

C'est ca ! Comme le ferais un

$('menu1 a').click(function(){

et

$('menu2 a').click(function(){

:)

NotANumber, il y a 12 ans

pourquoi ne pas parser ton URL et en fonction du resultat, tu execute une méthode.
Par exemple :

<a href="mon_site/toto"></a>
<a href="mon_site/tutu"></a>

$window.bind('statechange',function()
{
    var url = State.url;

    switch(url)
    {
        case 'mon_site/toto':
            maMethode1();
        break;
        case 'mon_site/tutu':
            maMethode2();
        break;
    }
});
function maMethode1()
{
    //
}
function maMethode2()
{
    //
}

C'est un exemple simplifié.
Il y a moyen de le rendre plus souple et plus propre.

joxs, il y a 12 ans

Oui j'avais pensé à cette solution mais le problème c'est que je vais devoir gérer facilement une centaine de liens uniques et ça serais facilement le bazar !
On peut pas coupler un bind click et un bind statechange ?

joxs, il y a 12 ans

J'ai trouvé une solution ! Toute bête et peut être un peu moche mais bon :

$('menu1 a').click(function(){
    var menu = menu1;
});
$('menu2 a').click(function(){
    var menu = menu2;
});

$window.bind('statechange',function(){
if (menu === menu1) {
    //
}
if (menu === menu2) {
    //
}

Merci pour tout :)

Edit: ne fonctionne pas

antho07, il y a 12 ans

Bonjour

$('.menu a').click(function(event){
var url = event.target.href;
//travaille peut être sur l'url pour juste garder la fin, une petite regex fera surement l'affaire
if(url == ... ){
..
}else if (url == .. ){
..
}
});

cordialement

Antho

antho07, il y a 12 ans

Peut être même mieux:

admettons que si le lien et "mon_site/toto" tu dois appeler la fonction toto :

var url = event.target.href;
var tab = url.split('/');
url = tab[tab.length -1];
eval(url+'()');

cordialement..Antho

joxs, il y a 12 ans

Merci Antho mais ce n'est pas ce que je cherche !
Ces variables retounent l'url et non pas le bouton sur lequel on à cliqué !

antho07, il y a 12 ans

Mais attention à l'injection de code avec ça...

antho07, il y a 12 ans

Le bouton c'est à dire??

event.target te renvoit le bouton enfin l'objet js associé au bouton cliqué

fait un $(".menu a").click(function(event){
event.preventDefault();
console.dir(event.target);
});

Tu verras tout ce que tu peux récuperer avec

sachant que tu peux aussi mettre un attribut html

data-truc sur chaque bouton et le recuperer par

event.target.dataset.truc

joxs, il y a 12 ans

Exemple:

<nav class="menu1">
    <a>fo</a>
    <a>fo</a>
    <a>fo</a>
</nav>
<nav class="menu2">
    <a>fo</a>
    <a>fo</a>
    <a>fo</a>
</nav>

J'aimerais savoir sur quels liens de quel menu on à cliqué, ce qui est possible avec ca :

$('menu1 a').click

Tu vois comment faire ?

antho07, il y a 12 ans

div class="menu" div class="menu1" a a a a /div div class="menu2" a a a a /div /div [code] $('. menu a').click(function(event){ event.preventDefault(); var menu = event.target.parentElement.className; }); [/code] ou [code]

a a a a

a a a a
[code] event.target.parentElement.dataset.menu [/code] ou plus simple on met le data-menu sur chaque lien du menu et dans ce cas [code] event.target.dataset.menu[/code] etC...

joxs, il y a 12 ans

Oui mais avec la fonction

$window.bind('statechange',function()

? Je n'arrive pas à connaitre le bouton qui à fait le 'statechange'

antho07, il y a 12 ans

ça fait quoi statechange ça repere quand l'url est changé??

antho07, il y a 12 ans

Tu peux expliquer en français exactement ce que tu veux récupérer et a quel moment? :$

J'ai un peu de mal à situer, quand on clique sur un bouton on peut tout récupérer .. toi tu veux que si on change l'url à la main, chercher le bouton dans la page qui aurait fait ce changement?

joxs, il y a 12 ans

En fait quand on clique sur un lien dans le menu, l'url est changé et le statechange le voit, ce qui lance une fonction !
Ce que j'aimerais savoir c'est quel lien à fait que le statechange à été modifié, je sais pas si tu vois ?
Regarde le js d'ajaxify-html5 pour essayer de mieux comprendre peut être :)

antho07, il y a 12 ans

Tu l'as bien le this non ??

// Ajaxify Helper
        $.fn.ajaxify = function(){
            // Prepare
            var $this = $(this);

            // Ajaxify
            $this.find('a:internal').click(function(event){
                // Prepare
                var
                    $this = $(this),
                                         menu = $this.parentElement.className, <=== la tu peux le chopper
                    url = $this.attr('href'),
                    title = $this.attr('title')||null;

                // Continue as normal for cmd clicks etc
                if ( event.which == 2 || event.metaKey ) { return true; }

                // Ajaxify this link
                document.title = title;
                history.pushState(null,title,url);
                $(window).trigger('popstate');
                event.preventDefault();
                return false;
            });

            // Chain
            return $this;
        };

tu peux ensuite le récuperer dans le popstate:
initialise la variable $menu à null en haut pour être sur qu'elle soit globale au plugin si tu veux..

joxs, il y a 12 ans

Ah super merci beaucoup Antho, je vous tient au courent de ce que j'arrive à faire :)

NotANumber, il y a 12 ans

J'ai du mal à voir l'intêret de savoir sur quel bouton on a cliqué.
Sauf si c'est pour mettre ton bouton en surbrillance...

Dans la logique des choses, lorsque tu clique sur ton bouton, tu change l'url avec pushState.
Lorsque l'url a changé, le stateChange t'envoie un évènement. Là, tu récupère l'url, tu la parse et tu fait ce que tu veux après ( changement de page, ect ) comme ça, lorsque tu cliquera sur suivant / précédent de ton navigateur, l'évènement stateChange sera éxecuté...
En gros, c'est ton url qui est le point d'entrée. ( même pour mettre tes boutons en surbrillance )
Mais c'est un peu compliqué a expliquer comme ça :p

joxs, il y a 12 ans

C'est vrai que le cas est vraiment particulier et compliqué à comprendre !

En fait je dois savoir sur quel bouton on a cliqué pour savoir quel serva le container à charger en Ajax, si c'est le menu1, ce sera #content, si c'est le menu2(qui est à l'intérieur de #content) ce sera #single(qui lui aussi est à l'intérieur de content)!

Je passerais un lien lorsque le site sera en ligne pour vous montrer :)

joxs, il y a 12 ans

Bon en fait la solution ne fonctionne pas car le

$window.bind('statechange',function(){

est récupéré avant le

$this.find('article a').click(function(event){

apparament...
La solution que j'ai trouvé et qui ne me plait pas c'est de créer trois fois le système : une fois normal :

$window.bind('statechange',function(){

;
Un autre pour le menu1 :

$('menu1 a').click(function(){

;
Un autre pour le menu2 :

$('menu2 a').click(function(){

;

Le problème encore c'est que la seule solution pour que le système fonctionne avec le menu2 une fois qu'il à été changé c'est de recharger le script avec

$.getScript("/js/ajaxify-html5.js");

Il y à-t-il une autre solution pour qu'il regarde les nouvelles infos ?

antho07, il y a 12 ans

Si j'ai bien compris, la première partie de l'url est différente selon le menu non?

Ou si tous les liens sont differents (il n'y a pas 2 fois le même lien dans 2 menu différent ) alors mode bourrin:
dans le ul qui contient le sous menu donne aussi la classe "un" "deux" "trois" qui correspond au menu du lien
Ensuite

$(document).ready(function(){
var url = window.location.pathname;
var class = $('#moving_tab a[href="'+url+'"]')[0].parentElement.parentElement.parentElement.parentElement.className; // A OPTIMISER !!! Là c pour voir si ça marche uniquement!
$('.aside_menu li').removeClass('active');
$('.aside_menu li .'+class).addClass('active');
});
joxs, il y a 12 ans

Pour l'instant oui, mais plus tard non, c'est ça le problème !

antho07, il y a 12 ans

Mais attention tu as des liens identiques dans les menus là donc ça ne va pas marcher, essaye en mettant des liens différents

EDIT: quand on clique sur le lien? ou que ça mette le bon menu en clair quand on charge le site sur une url précise??

joxs, il y a 12 ans

Dans le menu du bas ?

antho07, il y a 12 ans

sur le ul qui contient l'article: genre ça:
Officia deserunt mollitia
At vero eos et accusamus et iusto odio dignissimos ducimus.
6:32 | 13 vues | Ajouté le 23 juin 2013

joxs, il y a 12 ans

Ah oui ! Je ne comprend pas ta question

Le plus simple ne serais pas de faire un skype ? :p

antho07, il y a 12 ans

Parce que si récuperé juste le menu du haut qui correspond au lien cliqué

$('aside article a').click(function(event){

event.target.parentElement. ... .className (la classe de l'ul que taura mise identique à la classe du menu)

antho07, il y a 12 ans

pour le skype si tu veux

antho07, il y a 12 ans

envoit moi ton pseudo skype à ...]
dis moi quand c'est fait, je laisse pas mon mail trainé sur le forum ...

joxs, il y a 12 ans

c'est fait !

antho07, il y a 12 ans

demande envoyée

joxs, il y a 12 ans

Au final, antho à réussit à trouver la solution:

$.fn.ajaxify = function(){
    // Prepare
    var $this = $(this);

    // Ajaxify
    $this.find('a:internal:not(.no-ajaxy)').click(function(event){
        // Prepare
        var
            $this = $(this),
            url = $this.attr('href'),
            title = $this.attr('title')||null;
      if(this.parentElement.parentElement.parentElement.id == "nav" ){ //on regarde quel menu à bougé
            $isMenu = true;
        }else{
            $isMenu = false;
        }
        // Continue as normal for cmd clicks etc
        if ( event.which == 2 || event.metaKey ) { return true; }

        // Ajaxify this link
        History.pushState(null,title,url);
        event.preventDefault();
        return false;
    });

    // Chain
    return $this;
};
...]
    $window.bind('statechange',function(){
            // Prepare Variables
            var
        State = History.getState(),
                url = State.url,
                relativeUrl = url.replace(rootUrl,'');
            if($isMenu) { // on change en fonction du menu
                contentSelector = '#content',
                $content = $(contentSelector).filter(':first');
            }else{
                contentSelector = '#single',
                $content = $(contentSelector).filter(':first');
            }
...]

Voilà en espérent que ca va en aider !