11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous, je suis nouveau, j'espère donc poster au bon endroit. J'ai fouillé ce site ainsi que beaucoup d'autres avant de me décider à poster cette question au sujet de mon problème, qui est le suivant:

Je souhait que mon menu remplace le contenu d'un <div id="content">contenu de l'index</div> par un autre <div id="content>Contenu de la page deux</div> a partir d'une autre page (comportant elle aussi un header, body, ...). D'après ce que j'ai trouvé on appelle ça des pages dynamiques et ce genre de pratique nécessite une modification de l'url pour garder une trace dans l'historique... Sachant que le tout doit se faire avec une transition pour le départ de l'ancien div (contenu pars du milieu vers la gauche) et l'apparition de celui qui le remplacera (de la droite vers le milieu).

Les pages portent l'extension .php parce qu'elles comportent des includes. Et pour cause les dossiers et fichiers sont organisés comme ceci:

Le dossier racine /www/ contient
en fichiers -> index.php, -> favicon.gif.
en Dossiers: -> fonctions, -> images, -> includes, -> pages, ->styles.

*Le dossier includes contient des fragments de page qui sont répétitifs (menu, header, footer...)
(ces fragments sont inclus pour des raisons pratiques: 1 modification se répercute sur toutes mes pages.)

*Le dossier pages contient mes pages (autre que l'index).

Vous l'aurez compris: l'index est à la racine (/index.php), mon menu est dans le dossier includes (/includes/menu.php), mes autres pages sont dans le dossier pages: (/pages/page_1.php) & (/pages/page_2.php), elles ne sont donc pas au même niveau, elles ne contiennent donc pas les mêmes chemins relatifs.

L'ajax, le javascript, ne me font pas peur... Mais tous les liens que j'ai visité sont soit:

1)avec des pages en .html, (le traitement des hash enlève 5 caractères)
2)avec toutes les pages à la racine, (les chemins relatifs deviennent un problème)
3)ou alors le contenu du div est importé à partir de ça "case 'index': $contenu = 'Contenu de la page"Index"'; break;" Or moi c'est entre deux pages.

Les tentatives que j'ai mené ont bien modifié l'url avec le hash... mais la "destination" du href vers les pages ne menait nulle part à cause de la présence des hash.

Donc en guise de synthèse, j'ai besoin de faire un script (js, ajax) qui donne ceci :

http://sudojesse.github.io/dynamic-page/index.html
http://css-tricks.com/dynamic-page-replacing-content/
(mais les liens du menu ne mènent pas a mes pages avec ça)

Avec des pages .php
Avec mon arborescence et entre des "div" contenus dans deux pages
Avec une animation "drop left".

S'il-vous-plaît... Je vous en prie aidez-moi, ça fait 48h que je passe dessus sans y arriver... Je pourrais tuer un agneau a coup de parpaing Smiley bawling .
Je vous remercie d'avance pour vos conseils.
Modifié par Claod (09 Feb 2015 - 14:44)
Re-bonjour, (un petit up) avec des explications supplémentaires ...

voici l'exemple concret de ce que je cherche a faire :

1)Je suis sur l'index, je clique sur mon menu,

2)selon le lien cliqué j'aimerais récupérer le contenu de la div dans la page de destination. (url de la page, div id="content")

3)en se basant sur l'url de destination produire le hash en tronquant 2 caractère avant (si c'est l'index),ou 3 caractères (si c'est une autre page) . Et tronquer les 4 caractères de fin pour enlever le .php

4)faire partir l'ancien contenu du milieu en drop left, charger le nouveau de la droite vers le milieu.

5)modifier l'url avec le hash. Pour pouvoir cliquer sur précédant.

Ce qui me pose problème c'est
-récupérer le contenu de la div a partir de l'autre page,
-Créer le hash,
-Modifier l'url.

En espérant que je suis assez précis et que quelqu'un passera par là. Smiley sweatdrop
C'est toujours aussi incompréhensible... Enfin bon voici une piste, rapidement :
jQuery(function($){
   // le DOM est prêt

   // Je suppose que tu as des <a> dans une un élément #menu
   // (a adapter selon ta structure html)
   $('#menu a').click(function(){
      // supposons que ton href="/pages/maPage.php"
      var lien = $(this).attr('href');
      var hash = lien.match( /\/pages\/(.*).php/ )[1]; // on extrait juste le nom de la page
      location.hash = hash; // on change l'ancre dans l'url par le hash extrait
   });

   // Evenement au changement d'ancre
   $(window).on('hashchange' , function(){
      // on reconstruit l'url de la page
      var url = '/pages/' + location.hash.substring(1) + '.php';
      // Supposons que la <div> ou tu veux charger ton contenu ait un id="container"
      $( "#container" ).load( url + " #content" );
      // et #content c'est l'id de l'élément ou tu va chercher ton contenu dans ta page PHP
   });
});
Oh, vous ne pouvez pas savoir à quel point je suis content ! Bonjour Freez, merci merci merci d'avoir répondu !
arfh, désolé pour les explications c'est vrai que c'est assez compliqué.

Oui, dans mon menu c'est ainsi :


<div id="menu">
        <ul>
          <li class="menu-debut"><a href="../index.php">Accueil</a></li>
          <li class="menu-milieu"><a href="../pages/news.php">News</a></li>
          <li class="menu-milieu"><a href="../pages/page_2.php">Page 2</a></li>
          <li class="menu-milieu"><a href="../pages/page_3.php">Page 3</a></li>
          <li class="menu-fin"><a href="../pages/fin-menu.php">Fin du menu</a></li>
        </ul>
</div>


Première question:
je ne suis pas sur de comprendre le hashage ci-dessous:
 var hash = lien.match( /\/pages\/(.*).php/ )[1];

-Vous enlevez tout ce qui précède le premier "/" et ce qui suit le nom de la page a partir du deuxième "/" de façon à ce qu'il ne reste plus que les caractères autre que les "/" et le ".php"à la fin Puis vous attribuez la chaîne restante à la variable "hash" .
-Et le [1] est là uniquement pour le "location.hash.substring(1)" plus bas ?

Pour mes chemins relatifs "../pages/maPage.php" cela donnerait donc bien

var hash = lien.match( /..\/pages\/(.*).php/ )[1]


EDIT: non votre proposition coupe dejà les points c'est parfait ! Smiley lol

Ensuite
location.hash = hash;

modifie l'url en ajoutant #maPage à la fin. C'est donc pour le navigateur...
Et si l'utilisateur fait précédent dans son navigateur, l'historique a-t-il stocké les données nécessaires ? Ne dois-je pas faire quelque chose du genre
history.pushState()


Puis ici :
var url = '/pages/' + location.hash.substring(1) + '.php'

Chose que je ne faisais pas avant on recréé l'url avec
la chaine '../pages/' devant, le contenu de la variable hash : "maPage" puis .php comme extension.
Ca c'est le chemin qui mène à la page a charger, je ne faisais pas la distinction... comment j'ai pu zapper ça ! Smiley rolleyes
(A ce niveau là il faudra donc que je prévois une exception pour la page "index.php" qui ne se trouve pas dans le dossier "pages", il faudra que je prévois une exception en comparant la chaîne contenu dans la variable hash.)

Enfin,
$( "#container" ).load( url + " #content" );

charge dans le (div id="container") de ma page actuelle, le contenu du (div id="content") de la page se trouvant au chemin contenu dans la variable "url".

Donc là on a un script qui :
1)permet de changer l'url de ma page
2) en ajoutant un hash à la fin (qui dépend du lien cliqué sur mon menu.)
3) Et qui charge le contenu d'une div à partir d'une page externe en se référant à son ID.
C'est exactement ça que je cherchais !


Je vous remercie pour votre aide ! Ca m'a vraiment fait avancé ! Smiley ravi

En me renseignant j'ai buté sur un problème de plus, .load() va charger un contenu, mais je ne sais pas comment ajouter la transition .drop( {direction: left}) en fondu pour le contenu qui part et celui qui arrive... Smiley ohwell Auriez-vous une idée s'il vous plaît?

Je vous souhaite une bonne soirée !
Modifié par Claod (10 Feb 2015 - 00:51)
Content de vous avoir aidé, pour ce qui est de vos questions :

1 .
var hash = lien.match( /\/pages\/(.*).php/ )[1];
Ici j'extrait une partie de chaine de caractères par expression régulière, si vous ne savez pas ce que c'est il y a beaucoup de doc sur le sujet sur les internets. La méthode 'match' appelée depuis la chaine de caractère 'lien' (qui est le href du lien cliqué) retourne un tableau contenant les différentes correspondances entre la chaine de caractère et l'expression régulière passée en paramètre. Pour l'url "/pages/news.php" par exemple ça me retournerait :
["/pages/news.php", "news"]
Du coup ici je vais chercher uniquement le nom de la page, c'est à dire la valeur du tableau à l'index 1, voila pourquoi
lien.match( ... )[1];

2 .
Il me semble que le changement de hash suffit au navigateur pour historiser (avec Chrome et FF en versions récentes ça suffit en tout cas).

3 .
Pour la transition voulue, il faut vous débrouiller pour que la transition ait lieu après le chargement des données pour ne pas voir contenu apparaitre subitement. La fonction load prend en second (ou troisième) paramètre un callback qui s'execute une fois les données récupérées en AJAX.
$( "#container" ).load( url + " #content", function(){
   // c'est maintenant qu'il faut lancer la transition
} );
Bonjour ! Smiley biggrin

Alors oui effectivement, entre ma dernière réponse et la votre j'ai réussi à comprendre pour le hash.
C'était nécessaire pour les conditions que je voulais rajouter, je ne comprenais pas cette accumulation de slash... Mais finalement un / pour tronquer ce qu'il y a avant, un anti-slash pour que le slash suivant soit pris en compte comme caractère avec le mot qui suit... Bref aucune difficulté majeure juste des neurones embrouillés.

Il reste a inclure les transition mais ...
Pour le reste c'est tout ok !

J'en suis ici pour le moment:


jQuery(function($){
  
   $('#menu a').click(function(){
      var lien = $(this).attr('href');
	  if (lien == "../index.php") {
	  var hash = lien.match( /..\/(.*).php/ )[1];
	  } 
	  else {
	  var hash = lien.match( /\/pages\/(.*).php/ )[1];
	  }
      location.hash = ("#"+hash);
   });

   $(window).on('hashchange' , function(){
	  if(hash == "index") {
	  var url = '../' + location.hash.substring(1) + '.php';
	  }
	  else {
	  var url = '../pages/' + location.hash.substring(1) + '.php';
	  }
      $( "#content" ).load( url + " #content" ); // Oui, c'est chargé dans le même bloc ID mais dans une page différente. La transition sera ici d'après ce que vous m'avez dit.
   });
});


J'espère ne pas avoir fait de bêtises Smiley murf

J'étais certain qu'alsacréations me déboquerait, vous êtes un membre qui fait un travail remarquable et je ne vous remercierai jamais assez pour votre aide Smiley smile !
Modifié par Claod (10 Feb 2015 - 18:37)
EDIT : ça marche, parcontre si je rafraîchis la page le hash reste mais je retourne sur le contenu de l'index une idée ?



jQuery(function($){
  
   $('#menu a').click(function(e){
	   
      var lien = $(this).attr('href');
	  
	  if (lien == "../index.php") {
	  var hash = lien.match( /..\/(.*).php/ )[1];
	  } 
	  else {
	  var hash = lien.match( /\/pages\/(.*).php/ )[1];
	  }
      window.location.hash = hash; //remplace l'url par url+hash
	  e.preventDefault(); //empêche d'utiliser la méthode classique qui charge toute la page.
      $( "#content" ).load( lien + " #content" );//ça charge le contenu comme voulu
   });
});



Plus que la transition ! Smiley murf
Modifié par Claod (10 Feb 2015 - 19:47)
Oui c'est parce que quand tu rafraîchis la page ça ne passe pas dans le 'hashchange', tu peux le forcer à passer dedans en faisant un $(window).trigger('hashchange') (dans ton doc.ready), ou alors un petit trick :
location.hash = location.hash || 'index';
comme ça s'il n'y a rien dans le hash ça mettra automatiquement index, sinon ça mettra ce qu'il y a dans le hash, c'est un doublon voulu comme ça il passe par l'évènement "haschange"
Je ne suis pas sûr de comprendre votre méthode,

j'avais pensé à quelque chose comme ça



var hash = window.location.hash.substr(1);
var href = $('#menu ul li a').each(function(){
    var href = $(this).attr('href');
    if(hash==href.substr(0,href.length-4)){
        var toLoad = hash+'.php #content';
        $('#content').load(toLoad)
    } 
});


Avant tout mon code, de façon a vérifier le hash présent et rediriger la page actuelle vers le bon url... mais ça ne marche pas. Donc je vais essayer de comprendre votre solution Smiley sweatdrop
Le souci actuel c'est que si je clique sur un lien puis que je rafraîchis, l'url a le bon hash, mais le content chargé dynamiquement retourne à celui chargé initialement (index).
Je cherche mais j'admet que si vous avez une idée, ça serait super car le

location.hash = location.hash || 'index';

ne fonctionne pas. Il ajoute certes un #index quand je suis sur l'index mais c'est tout. Smiley sweatdrop
il faut mettre le location.hash = location.hash || 'index'; après avoir déclaré le $(window).on('hashchange'...) sinon ça ne fonctionnera évidemment pas.
C'est peut être pas propre de faire comme ça, à vous de me dire....
mais j'ai réussi en faisant comme suit :



location.hash = location.hash || 'index'; //si on arrive sur la page #index apparait.
	
	var hash = window.location.hash.substr(1); //hash prend la valeur actuel du hash dans l'url
	if(hash=='index') { var hashpage = '../index.php'; } //si le hash est "index" redirige vers la page index
	else { var hashpage = '../pages/'+hash+'.php'; } // sinon on recalcule l'url de la page a partir du hash
	$('#content').load(hashpage + " #content") // puis on charge le contenu a charger avec l'url recalculée
	


Cela vous parait-il pro ?

Je ne vois pas ou mettre vos ligne, ni quelles fonctions elles ont Smiley ohwell

EDIT: ça empêche d'utiliser le bouton page précédante, et si on change le hash on ne put pas rejoindre la page voulue... grrrrr Smiley biggol
Modifié par Claod (10 Feb 2015 - 22:36)
AH ! I've got it !

Ca y est j'ai compris, enfin me direz vous...

Finalement ce javascript est divisé en 3 partie,
Une pour que le contenu apparaisse selon le hash
Une pour que le rafraîchissement fonctionne (que le hash mène au contenu donc),
et une pour que le bouton page suivant, page précédente fonctionne... en gros ça permet de voir si le hash a changé entre le chargement du document et celui ou on actualise l'url.

(finalement pour la dernière étape il fallait vérifier tout au long du javascript si le hash change, pour réattribuer le bon contenu selon ce qu'il y a dans l'url.)

Donc là il ne reste plus que les transitions à mettre . Le tout donne ceci:



jQuery(function($){
	
	location.hash = location.hash || 'index';
	
	var hash = window.location.hash.substr(1);
	if(hash=='index') { var hashpage = '../index.php'; }
	else { var hashpage = '../pages/'+hash+'.php'; }
	$('#content').load(hashpage + " #content")
	
$('#menu a').click(function(e){
	   
      var lien = $(this).attr('href');
	  
	  if (lien == "../index.php") {
	  var hash = lien.match( /..\/(.*).php/ )[1];
	  } 
	  else {
	  var hash = lien.match( /\/pages\/(.*).php/ )[1];
	  }
      window.location.hash = hash;
	  e.preventDefault();
      $( "#content" ).load( lien + " #content" );
   });
   
$(window).on('hashchange' , function(){
	var hash = window.location.hash.substr(1);
	if(hash=='index') { var hashpage = '../index.php'; }
	else { var hashpage = '../pages/'+hash+'.php'; }
	$('#content').load(hashpage + " #content")
   });
});

Modifié par Claod (10 Feb 2015 - 23:22)
Version optimisée :
jQuery(function($){
   $('#menu a').click(function(e){	   
      e.preventDefault();
      var lien = $(this).attr('href');	  
      var hash = (lien === "../index.php") ? 'index' : lien.match( /..\/(.*).php/ )[1];
      // et oui, pourquoi matcher avec une expression régulière si on est sur que c'est l'index?      
      location.hash = hash;	 
   });
   
   $(window).on('hashchange' , function(){
      var hash = location.hash.substr(1);
      var hashpage = (hash === 'index') ? '../index.php' : '../pages/'+hash+'.php';
      $('#content').load(hashpage + " #content")
   });

   // comme suggéré quelques messages plus haut, suffisait de mettre cette ligne a la fin
   location.hash = location.hash || 'index'; 
});
Smiley ohwell
La version optimisée ne marche pas quand je l'intègre...
J'essaie de trouver ou ça coince, mais pour ça il faudrait que j'arrive à capter cette ligne :
 var hash = (lien === "../index.php") ? 'index' : lien.match( /..\/(.*).php/ )[1];


hash = index, si lien = ../index.php, sinon hash = "on élague les ../" on récupère ce qu'il y a entre deux, et "on élague .php"

C'est ça ? Smiley sweatdrop


De mon coté le hash devient #/pages/page_01 et ne change pas le contenu,
Changer le hash dans l'url et valider ne fait rien,
revenir en arrière change le hash mais comme le contenu n'a pas changé il n'y a pas de différence,
et rafraichir rafraichit l'index, même si on a ajouté un hash #/pages/page_01 Smiley confus
Vérifie bien ce qu'il y a dans $(window).on('hashchange' , function(){ ... , normalement le code que je t'ai fourni doit fonctionner, on le force à passer dans le hashchange, c'est ce qui se passe dans la fonction qui doit poser problème. Fais progressivement des console.log( ) de tes valeurs pour être sur que c'est bien ce que tu attends, tu vas trouver Smiley cligne
ah haha ! je l'ai !


jQuery(function($){
   $('#menu a').click(function(e){	   
      e.preventDefault();
      var lien = $(this).attr('href');	  
      var hash = (lien === "../index.php") ? 'index' : lien.match( /..\/(.*).php/ )[1]; // Voilà la petite #méchant-mot# enfaite le lien on l'a matché pour l'index alors on élague pas le dossier 'pages', du coup le hash est mal créé, et le lien crée ensuite est faussé ! ici c'était  :  .(match(/pages\/(.*).php/)[1];)
      // et oui, pourquoi matcher avec une expression régulière si on est sur que c'est l'index?      
      location.hash = hash;	 
   });
   
   $(window).on('hashchange' , function(){
      var hash = location.hash.substr(1);
      var hashpage = (hash === 'index') ? '../index.php' : '../pages/'+hash+'.php';
      $('#content').load(hashpage + " #content")
   });

   location.hash = location.hash || 'index'; 

	
	 var hash = location.hash.substr(1);
         if(hash == 'index'){ hashpage = '../index.php';}
	 else { hashpage = '../pages/'+hash+'.php';}
         $('#content').load(hashpage + " #content"); //ce block est ici sinon lors de la réactualisation on garde le hash mais le contenu dynamiquement chargé est perdu avec impossibilité de le re-loader (le hash est le même, donc ne change pas)
});



parcontre j'ai du remplacer
 var hash = (lien === "../index.php") ? 'index' : lien.match( /..\/(.*).php/ )[1];


par des conditions avec "if" et "else", la structure tel que vous l'aviez mis (avec la '?' et me ':') ne marchait pas Smiley ohwell
Modifié par Claod (11 Feb 2015 - 15:43)
voici le tout avec la transition Smiley smile

j'ai mis un overflow-x:hidden; dans le css du body pour cacher la scrollbar qui apparaissait et déplaçait temporairement mon background.
(comme il remplit la fenêtre, la barre apparaissait et changait donc la taille de celle-ci)

et le script:


jQuery(function($){
	  
   $('#menu a').click(function(e){	   
      e.preventDefault();
      var lien = $(this).attr('href');  
      if(lien == "../index.php"){ var hash = 'index';}
	  else { var hash = lien.match( /pages\/(.*).php/ )[1];}
      location.hash = hash;
   });
   
   $(window).on('hashchange' , function(){
      var hash = location.hash.substr(1);
      if(hash == 'index'){ hashpage = '../index.php';}
	  else { hashpage = '../pages/'+hash+'.php';}
      $('#content').animate({ 
	  right: "800px", opacity: '0'
	  },200).animate({
		   right: "-=1600px"
		   },0,'', function() { $('#content').load(hashpage + " #content")}).animate({
			   right: "+=800px", opacity: '1'
			   }, 200);
   });

	 var hash = location.hash.substr(1);
     if(hash == 'index'){ hashpage = '../index.php';}
	 else { hashpage = '../pages/'+hash+'.php';}
     $('#content').load(hashpage + " #content"); 
});


C'est sans doute pas parfait, je peux peut-être améliorer quelque chose?

Mais même si c'est le cas ... ça rend EXACTEMENT comme je voulais. Je suis difficile à satisfaire, c'est un exploit !


Merci mille-fois Freez !!!! Vraiment! Smiley smile