Mettre à jour toute la page sur la demande d'Ajax

J'ai une requête AJAX qui peut avoir deux résultats possibles:

  1. Le serveur répond avec un message que je devrais placer dans un <div>
  2. Le serveur répond avec une page HTML, dans ce cas, je dois remplacer la page actuelle par une nouvelle et modifier l'adresse (le client connaît l'adresse avant une demande).

Quelle serait la solution si j'ai la requête AJAX qui doit gérer ces deux cas?

  url = "http://example.com" ajax.request(callback) function callback(response) { if (case2(response)) { history.pushState({}, "New page", url); document.innerHTML = response } else { updateDiv(response) } } 

Je suis intéressé par un moyen correct de mettre en œuvre la première branche, ou si le serveur peut en quelque sorte composer des en-têtes qui rendent le navigateur pour gérer une réponse en tant que réponse HTTP habituelle et mettre à jour un emplacement et un contenu de la page, quelque chose comme la redirection vers un contenu donné .

Je comprends que le serveur peut renvoyer un lien au lieu d'une page, mais dans ce cas, une étape supplémentaire sera nécessaire sur un client – rediriger et ensuite remplir la nouvelle page sur le serveur.

Très franchement, je pense que cette approche est essentiellement rompue par la conception. Vous ne devriez pas avoir à prendre cette décision à cet endroit. Par exemple, la réponse ajax pourrait seulement signaler qu'une nouvelle page devrait être chargée et que le nouveau contenu soit généré sur une seconde requête (non-ajax) vers une nouvelle URL.

Dans le cas où vous êtes forcé de prendre la voie à suivre, et si le contenu de la réponse n'est pas très important, vous pouvez essayer les URI de Javascript. Fondamentalement, un URI sous la forme de javascript:"string" va charger une nouvelle page pour laquelle cette chaîne est le code source. Donc, si la response est déjà une chaîne, il suffit d'attribuer javascript:response à window.location.href devrait suffire. Peut-être que vous devez faire échapper à l'avance. Et je ne sais pas, quelle approche est compatible avec ce navigateur.

 <a href="javascript:response">load</a> 

Est également possible.

Une variante de ceci consiste à créer l'URL non avec le nom de la variable, mais avec les données de chaîne réelles. Comme

 function source2url(src) { // make valid javascript string from source text var esc1 = src .replace(/\\/g, '\\\\') .replace(/\'/g, '\\\'') .replace(/\x0A/g, '\\x0A') .replace(/\x0D/g, '\\x0D'); // make valid url from that return "javascript:'" + encodeURIComponent(esc1) + "'"; } window.location.href = source2url(response); 

Cela générera bien sûr des URI assez importants. Et vous aurez toujours l'URI Javascript dans la barre d'adresse.

METTRE À JOUR

Une approche similaire consiste à utiliser l'encodage base64 dans un URI de données. L' entrée Wikipedia explique comment cela fonctionne, y compris un exemple javascript. Cependant, vous devriez bas64 coder le contenu en quelque sorte. (Remarque: Vous pouvez utiliser des URI de données avec ou sans codage base64. Vous devez voir ce qui vous donne des URI plus courts pour votre contenu spécifique.)

J'ai eu un problème similaire une fois. Une page d'erreur complète a été retournée au lieu d'un simple fragment HTML. Nous avons finalement réglé cela en changeant la logique, mais voici l'une des solutions que j'ai trouvées:

 document.open(); document.write(responseText); document.close(); 

La raison pour laquelle nous avons abandonné cela, c'est que sur IE, il y avait des problèmes. Je n'ai perdu aucun temps pour enquêter sur la raison, mais il a lancé une exception «Accès refusé» lors de la tentative d'écriture de la chaîne. Je pense qu'il y avait des marqueurs <meta> qui confondaient IE, ou peut-être des commentaires conditionnels, je ne suis pas sûr. (Cela a fonctionné lorsque j'ai utilisé des pages simples …)

La ligne de fond est: vous ne devriez pas faire cela, mais s'il n'y a rien d'autre que vous pouvez faire (comme le retour d'une chaîne d'URL), le code ci-dessus pourrait fonctionner.

C'est vraiment simple si la réponse est un XML valide.

 var new_doc = (new DOMParser).parseFromString(response, "application/xml"); document.replaceChild(document.adoptNode(new_doc.doctype), document.doctype); document.replaceChild(document.adoptNode(new_doc.documentElement), document.documentElement); 

Puisque la demande est pour une réponse mise à jour, voici ma solution en utilisant l' API historique HTML5 avec jQuery . Il devrait fonctionner facilement en combinant les parties PHP et HTML en un seul fichier.

Ma solution permet à AJAX de renvoyer ce qui suit:

  1. Un message via AJAX, qui met à jour un conteneur <div> .
  2. Une URL qui provoque le redirection vers l'URL
  3. Une page HTML complète qui appelle history.pushState() de l'API Historique pour ajouter l'URL actuelle à l'historique du navigateur et remplace le HTML complet sur la page avec le code HTML renvoyé par AJAX.

PHP

Ce n'est qu'un exemple de ce que le script PHP devra retourner lorsqu'il est invoqué via AJAX. Il montre comment coder les indicateurs pour déterminer si l'appel AJAX doit mettre à jour le conteneur ou charger une nouvelle page, et comment renvoyer son résultat via JSON via json_encode . Pour l'exhaustivité, j'ai nommé ce script test.php .

 <?php // Random messages to return $messages = array( 'Stack Overflow', 'Error Message', 'Testing' ); // If the page was requested via AJAX if( isset( $_POST['ajax'])) { $response = array( 'redirect' => // Flag to redirect ( rand() % 2 == 0) ? true : false, 'load_html' => // Flag to load HTML or do URL redirect ( rand() % 2 == 0) ? true : false, 'html' => // Returned HTML '<html><head><title>AJAX Loaded Title</title></head><body>It works!</body></html>', 'title' => 'History API previous title', 'message' => // Random message $messages[ (rand() % count( $messages)) ] ); echo json_encode( $response); exit; } 

JS

Puisque j'utilise jQuery, commencez par cela. Ce qui suit transmet un AJAX POST au serveur, au script PHP ci-dessus à l'URL test.php . Notez qu'il définit également le paramètre POST ajax comme étant true , permettant au script PHP de détecter qu'il a reçu une requête AJAX. Le champ dataType indique à jQuery que la réponse du serveur sera dans JSON et qu'il décodera ce JSON sur un objet JSON dans le rappel de réponse. Enfin, le rappel de success , qui est déclenché lorsque la réponse AJAX est reçue avec succès, détermine ce qu'il faut faire en fonction des drapeaux envoyés par le serveur.

 $.ajax({ type: 'POST', url: "/test.php", data: {ajax : true}, dataType: "json", success: function( json) { if( json.redirect) { if( json.load_html) { // If the History API is available if( !(typeof history.pushState === 'undefined')) { history.pushState( { url: redirect_url, title: document.title}, document.title, // Can also use json.title to set previous page title on server redirect_url ); } // Output the HTML document.open(); document.write( json.html); document.close(); } else { window.location = redirect_url; } } else { $('#message').html( json.message); } }, }); 

HTML

Voici la source HTML complète de mon fichier testé. Je l'ai testé dans FF4 – FF8. Notez que jQuery fournit la méthode ready pour empêcher le JS de s'exécuter jusqu'à ce que le DOM soit chargé. J'ai également utilisé l'hébergement de jQuery par Google, donc vous n'avez pas besoin de télécharger une copie de jQuery sur votre serveur pour vérifier cela.

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js" type="text/javascript"></script> <title>Default Page</title> <script type="text/javascript""> $( document).ready( function() { $('#ajax_link').click( function() { var redirect_url = "/test.php"; $.ajax({ type: 'POST', url: "/test.php", data: {ajax : true}, dataType: "json", success: function( json) { if( json.redirect) { if( json.load_html) { // If the History API is available if( !(typeof history.pushState === 'undefined')) { history.pushState( { url: redirect_url, title: document.title}, document.title, // Can also use json.title to set previous page title on server redirect_url ); } document.open(); document.write( json.html); document.close(); } else { window.location = redirect_url; } } else { $('#message').html( json.message); } }, }); }) }); </script> </head> <body> <div id="message">The default contents of the message</div> <a id="ajax_link" href="#">Fire AJAX</a> </body> </html> 

Donnez un identifiant au corps <body id="page"> et votre autre div sera <div id="message"></div> maintenant votre ajax ressemblera

  $.ajax({ url:'myAjax.php', data:{datakey:datavalue}, dataType:"JSON", success: function (response) { if(response.message=="your message") { $('#message').html(response.content); } else { $('#page').html(response.content); } } }); 

Comme le dit T-Bull … tout le processus est mal ici …

Vous ne faites que compliquer les choses et vous le savez bien:

Je comprends que le serveur peut renvoyer un lien au lieu d'une page, mais dans ce cas, une étape supplémentaire sera nécessaire sur un client – rediriger et ensuite remplir la nouvelle page sur le serveur.

Arrête de compliquer et commence à le faire bien …

  1. Le client ouvre la première page, alors, $_SESSION['tmp_client_id'] = 'client_'.session_id(); Évidemment, c'est mieux si le client est déjà souscrit, de toute façon, mettez des éléments dans la table temporaire OU dans une autre session, etc.
  2. Le client remplit le formulaire;
  3. Client soumettre le formulaire;
  4. Faire la demande AJAX;
  5. Store $_POST variable à l'intérieur de tmp_client_tbl avec son tmp_client_id unique ou seulement $_SESSION['client_'.session_id()] = json_encode($_POST);
  6. Résultat n ° 1? Affiche un message dans un </div>
  7. Résultat n ° 2? Actualisez la page et vérifiez if( isset($_SESSION['client_'.session_id()])) { si c'est le cas, nous allons afficher le formulaire à nouveau avec les champs remplis: } else { afficher le formulaire vide;
  8. SELECT * FROM tmp_client_tbl WHERE tmp_client_id = '{$_SESSION['tmp_client_id']}' OU json_decode($_SESSION['client_'.session_id()]);
  9. $form_data = $mysql_rows; OU $json_array;
  10. foreach($form_data as $name => $value) { echo "<input name='$name' value='$value' />" } d'une manière ninja qui supposent que vous avez un tel type de tableau de création de formulaire où $form = array('text' => array('name','lastname'), 'select' => array('countries'), ... ) , ou simplement par <input name='lastname' value='{$lastname}' /> où les valeurs des champs sont pré-poluées avec des vars vides;
  11. Temps écoulé, erreur survenue, navigateur fermé? session_destroy(); Ou unset($_SESSION['client_'.session_id()]);