IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Conception avec PushState | autre solution ?


Sujet :

JavaScript

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 85
    Par défaut Conception avec PushState | autre solution ?
    Bonjour,

    J'effectue un développement sous symfony 2 utilisant le routage de celui-ci et twig.

    J'ai intégré des appels Ajax pour éviter des chargements de page complètes. Comme tout le monde je souhaite néanmoins qu'un url corresponde à une donnée. J'utilise donc PushState de la bibliothèque History.js

    Scénario.
    1 - Je suis sur ma page accueil. J'effectue une recherche.
    2 - Je tombe sur une nouvelle page affichant un ensemble résultat.
    3 - Je clic sur suivant, pour afficher les résultats suivants, sans recharger la page, juste mettre à jour le bout d'interface nécessaire. J'utilise donc un appel Ajax.
    etc.

    Arborescence

    Sans Hisotry :
    1 - Accueil.
    2 - resultat/
    3 - resultat/
    etc...

    Avec :

    1 - Accueil/
    2 - resultat/page-1
    3 - resultat/page-2
    etc..

    Si je m’arrête là, la navigation via le navigateur est correct.

    On pense tout est génial. Hors je me confronte à un problème allant plus loin.

    4 - Je demande le détail d'une recherche, qui est un appel "normal" url.

    1 - Accueil/
    2 - resultat/page-1
    3 - resultat/page-2
    4 - details/2

    Je clic maintenant sur "précédent", retrouvant cet état :
    1 - Accueil/
    2 - resultat/page-1
    3 - resultat/page-2

    je re-clic sur précédent...

    1 - Accueil/
    2 - resultat/page-1
    3 - resultat/page-2

    "bug"

    De nouveau sur précédent

    1 - Accueil/
    2 - resultat/page-1

    "ok"

    J'ai un problème de conception selon moi et je ne vois pas comment le résoudre.

    Voici le code JS de la page "resultat".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    <script type="text/javascript">
    $(document).ready(function()
     
    //Première visite, on effectue un historique
    //"div_p_result" est le conteneur changeant à chaque appel Ajax
    // vpageStart et le numéro de la page courante (en effet, l'utilisateur peut très bien faire un copier coller d'une url et accéder directement pour la //première fois de cette interface à la page N
     
    var stateStartObj = { data: $('.div_p_result').html() };
    History.pushState(stateStartObj, window.document.title, "page-"+vpageStart);
     
    History.Adapter.bind(window, 'statechange', function()
    	{
    		var State = History.getState();
     
    	        History.log(State.data, State.title, State.url);
     
                    // On met à jour le conteneur
    		$('.div_p_result').empty();
    		$('.div_p_result').append(State.data.data);
    	});
     
    $('#test').click(function()
    			{
                                    // J'avoue, il y a surement mieux comme méthode de calcul de paramètre d'url...
    				loc='{{  app.session.locale}}';
    				//récupére l'url
    				var lien = document.location.href;
    				// décompte l'url
    				var stlien = lien.split("/");
    				//Nb items
    				lg = stlien.length;
    				//récupére la donnée continent (tableau commence à 0 )
    				var name = stlien[lg-2];
    				//récupére la donnée page
    				var vpage = stlien[lg-1];
    				//récupére la valeur page
    				vpage = Number(vpage.split("-")[1]);
     
     
    				$.get(Routing.generate('lookForByContinentPage', {'name':name,'page':vpage, '_locale':loc}), 
    						function(data){
          							var stateObj = { data: data };
    							var title = window.document.title;
    							var title = title.split("|")[0];
    							History.pushState(stateObj, title+"| page-"+vpage, "page-"+vpage);
    						});
    			}
    		);
     
    </script>
     
     
    <div class="button_look">
    	<input type="button" id="test" class="input_lookfor" value="go">
    </div>
     
    	<div class="div_p_result">
    			{% for result in listResult %}
                                  etc ...
    Comme vous le voyez, lors du premier appel de la page "resultat", on effectue un pushState pour "mémoriser" le contenu de conteneur (Sans cela, lors d'un forward jusque la "page-1" (dans l'exemple), on aurai le "conteneur" vide.
    Ensuite on effectue un PushState à la suite de chaque appel Ajax.
    Ensuite on passe à une autre page, exemple "détails d'une recherche" (appel url), le navigateur reprend la main de l'historique.

    Hors, lorsque de l'on revient, "bouton précédent", on recharge la page "resultat" et donc on re-effectue un pushState, ce qui donne ce scénario montré plus haut. Ce qui n'est pas souhaité du tout comme vous l'avez compris.

    Je n'arrive pas à voir comment je peut faire pour pallier ceci, qui est au bout du compte, une alternance Manipulation Historique ajax/js et Historique classique.

    Si vous auriez une vision ?

    Et pour compléter ceci, est-ce que History.js suffit, ou dois-je implémenter autre chose (angular/backbonne , que je n'utilise, ayant déjà le système de routage symfony et twig, pensant ne m'être utile..).


    Merci de m'avoir déjà lu.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Par défaut
    Salut,

    je n'ai pas encore eu l'occasion de me pencher sur la gestion de l'historique du navigateur mais pour ton problème ce que je ferai c'est simplement a chaque page, mémoriser le nombre d'élement dans l'historique.
    Comme ça par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sessionStorage.historyLength = window.history.length;
    et avant d'ajouter un nouvel element dans l'historique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if (!(sessionStorage.historyLength < window.history.length)) {
       History.pushState(stateStartObj, window.document.title, "page-"+vpageStart);
       // etc..
    }
    sessionStorage.historyLength = window.history.length;

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 85
    Par défaut
    Salut,

    Merci pour cette réponse.

    J'ai regardé alors à quoi correspondait sessionStorage, ne connaissant pas. C'est intéressant et c'est vrai que dans ce cas il faut utilisé "sessionStorage" et non "localStorage".

    Je pense bien comprendre que cela permet de stocker des données utiles, par exemple à la navigation dans ce cas.
    Principe de clé-valeur. sessionStorage.setItem('clé', 'valeur');

    Valable pendant la durée d’activité de la fenêtre ouverte du navigateur. Chaque élément enregistré par sessionStorage étant indépendante de chaque fenêtre ouverte et effacé à la fermeture de la fenêtre.

    Avant de tout implémenter ou faire plein de test j'ai testé dans mon esprit et me pose ces questions à termes.

    - le développeur va créer ses propres <clé-valeur> pour sont site

    A quel moment aura-t-on une atomicité de <clé-valeur>, dans le sens, un autre développeur aura créer le même attribut <clé-valeur>, qui peut générer un conflit.

    C'est à dire, l'utilisateur va ouvre un onglet et va sur le site domain1.com qui utilise la clé "historyLength" pour sessionStorage.
    L'utilisateur va ensuite sur mon site domain2.com, avec le même onglet, et j'utilise aussi la clé "historyLength"

    Il y a t-il conflit ?

    Juste confirmation, car si ma traduction en anglais est bonne, j'ai lu que chaque site (domain) à son propre storageSession (donc pas de conflit) "Each site has its own separate storage area."

    Tu as rencontré des contraintes à cette utilisation sinon ?

    Comme tu dis "à chaque page" mettre à jour le nombre d'historique (j'ai mis du temps à saisir, c'est déjà une belle contrainte. La cata s'il y a un oublie).
    Tu as utilisé cette notion de mise à jour au niveau du chargement du "menu", de ton site peut-être ? (c'est un bon moyen je trouve, étant chargé pour chaque page, pas de redondance de code)

    Merci c'est intéressant en tout cas. J'essaye de comprendre les limites/contraintes avant tout.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Par défaut
    Non, avec sessionStorage, pas de conflit possible avec d'autres domaines. On peut considérer ça comme une variable globale qui reste même si on change de page sur le site.
    Par contre je ne sais pas si sa reste en mémoire d'un onglet a l'autre (en ouvrant une page du site vers un nouvel onglet par exemple). Je ne pense pas, à vérifier.
    Pour les stockage longue durée il y a localStorage.

    Sinon comme je te l'ai dit je n'ai pas encore commencé a gérer ces problèmes d'historique donc je ne peut pas te dire comment je ferai pour mon site.

    Pour ton site, je pense qu'il faut que tu remette à jour la clé "historyLength" (exemple de nom) juste après chaque "pushState" de la façon indiqué dans mon exemple précédent.
    Mettre a jour a chaque page ça ne fonctionnera surement pas.
    Si "historyLength" est inexact sur les pages standards ça ne posera aucun problème.
    Ton bug se produit au retour sur une page contenant un "pushState" (et donc une mise a jour de "historyLength") donc automatiquement, comme tu revient, c'est que "historyLength" aura forcement été mis a jour pour te permettre d’éviter ce bug.

    J'ai juste un petit doute qui remet tout en cause. Qu'est ce qui se passera si tu fait un "pushState", tu avance d'une page puis tu ferme le navigateur.
    2 jours plus tard, tu r'ouvre et tu décide de faire un page précédent.
    Est que le sessionStorage aura gardé la variable ? non.
    Du coup le bug réapparaîtra a cette occasion.

    Donc a priori il vaut mieux utiliser localStorage pour stocker "historyLength".

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 85
    Par défaut
    J'ai testé voir, je suis parti directement avec LocalStorage. Je n'avais pas pensé à cette notion de fermer le navigateur et reprendre la navigation plus tard. Je n'utilise jamais cela et je ne crois même pas que je connaissais (j'ai cliqué sur Safari "rouvrir sur la dernière fenêtre ayant été fermé"), si c'est bien ce que tu disais ? en effet on peut refaire des "boutons précédents" et je ne vois pas trop l’intérêt d'avoir de ce type de navigation, mais d'accord, ça existe.

    J'ai implémenté alors et ça fait de la tambouille :s

    Le code, lors du chargement de la page (effectué lors du chargement complet de la page donc)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
    $(document).ready(function()
    {
     
    //localstorage est-il supporté par le navigateur 
    	if(typeof localStorage!='undefined') 
    		{
    		//la varialbe historyLength existe t-elle
    		if (localStorage.getItem("historyLength") === null) 
    			{
    				localStorage.setItem('historyLength', window.history.length);
                                    .....
    				History.pushState(stateStartObj, window.document.title, "page-"+vpageStart);
    		}else
    			{
    				if(!(localStorage.historyLength < window.history.length)) 
    				{
                                            .........
    					History.pushState(stateStartObj, window.document.title, "page-"+vpageStart);
    				}
    				localStorage.historyLength = window.history.length;
                            }
               }else{
                     // Faire autre chose
                    alert("localstorage pas supporté");
    	   }
    .......
     }
    1 - la condition if(!(localStorage.historyLength < window.history.length)) ne fonctionne pas comme attendu.
    peut s'écrire aussi if(localStorage.historyLength >= window.history.length)

    Vu comme cela, je me dis que cette condition ne sera pas vérifié

    Ex de navigation :
    - Page_accueil
    - Resultat_recherche/page1 (on créé "historyLength" , n'existant pas) = pushState : historyLength=history.length=2
    - Resultat_recherche/page2 (pushSate, via Ajax) : historyLength=2 ,history.length=3
    - Page_Autre (historisque navigateur) historyLength=2 ,history.length=4
    - Page_Accueil (historique navigateur) historyLength=2 ,history.length=5
    - Resultat_recherche/page1 (nouvelle recherche) (pas de pushState, la condition historyLength>=history.length invalide) historyLength= 2 history.length=5 (avant condition)(bug)

    Un exemple parmi d'autre malheureusement

    2 - LocalStorage va partager sa valeur "historyLength" entre les différents onglets ouvert (comme tu le disais), ce qui fausse d'avantage toute la navigation avec ce principe. D'autant plus lors d'une nouvelle session/navigation par exemple.


    Bien entendu, sessionStorage résoudra le 2eme problème, quand à la notion de "reouverture" de navigateur...

    ça ce trouve il ne manque pas grand chose, pour l'instant les pinceaux sont emmêlés.

Discussions similaires

  1. conception site: iframe ou autre solution
    Par Anubis dans le forum Balisage (X)HTML et validation W3C
    Réponses: 7
    Dernier message: 13/09/2010, 08h08
  2. Interchanger un JPanel avec un autre
    Par jfz dans le forum Agents de placement/Fenêtres
    Réponses: 10
    Dernier message: 09/01/2010, 20h38
  3. Liée table avec une autre base
    Par Thomad dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 18/01/2005, 09h06
  4. Réponses: 5
    Dernier message: 02/09/2004, 16h17
  5. [langage] Comparer Perl avec d'autres langages comme C ?
    Par Anonymous dans le forum Langage
    Réponses: 3
    Dernier message: 10/08/2002, 23h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo