30 votes

Mettre à jour toute la page sur la demande Ajax

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

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

Quelle serait la solution si j'ai de la requête AJAX qui doit gérer à la fois de ces 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 une bonne façon de mettre en œuvre la première branche, ou si le serveur peut en quelque sorte se composent d'un des en-têtes qui feront de navigateur pour manipuler une réponse comme d'habitude la réponse HTTP et mise à jour d'un emplacement de la page et le contenu, quelque chose comme de redirection avec le contenu.

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 le client de redirection, puis remplissage de la nouvelle page sur le serveur.

28voto

T-Bull Points 1136

Franchement, je pense que cette approche est fondamentalement brisé par la conception. Vous ne devriez pas avoir à prendre cette décision à cet endroit. Par exemple, l'ajax réponse ne pouvait signifier qu'une toute nouvelle page doit être chargée et le nouveau contenu alors être générée sur un deuxième (non-ajax) demande à une nouvelle URL.

Dans le cas où vous êtes obligé de prendre le chemin vous déjà aller, à condition que le contenu de la réponse n'est pas très grande, vous pouvez essayer de Javascript-Uri. Fondamentalement, un URI dans la forme d' javascript:"string" vous permettra de charger une nouvelle page de cette chaîne est le code source. Donc, si response est déjà une chaîne, tout en assignant javascript:response de window.location.href devrait suffire. Peut-être que vous avez à faire certains d'échapper à l'avance. Et je ne sais pas, comment la croix-navigateur compatible avec cette approche.

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

est également possible.

Une variante de cette approche est la construction de l'URL n'est pas avec le nom de la variable, mais avec la chaîne de données. 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);

Ce sera, bien sûr, de générer assez grand Uri. Et vous aurez toujours le Javascript-URI dans la barre d'adresse.

Mise à JOUR

Une approche similaire est d'utiliser l'encodage base64 dans les données d'un URI. L' entrée de Wikipedia explique comment il fonctionne, y compris un exemple en javascript. Cependant, vous auriez à en base64 encode le contenu en quelque sorte. (Remarque: Vous pouvez utiliser les données des URIs avec ou sans l'encodage base64. Vous devez voir ce qui vous donne plus courte Uri pour votre contenu spécifique.)

10voto

Dan Manastireanu Points 1260

J'ai eu un problème similaire une fois. Une pleine page d'erreur a été renvoyée à la place d'un simple fragment de code HTML. Nous avons finalement résolu ce par la modification de la logique, mais ici, c'est l'une des solutions que j'ai trouvées:

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

La raison pour laquelle nous abandonné c'est que sur IE, il y avait quelques problèmes. Je n'ai pas le droit de perdre tout le temps de chercher le pourquoi, mais il l'a jeté un "Accès refusé" d'exception lors de la tentative d'écrire la chaîne. Je pense qu'il y avait quelques - <meta> tags confondre IE, ou peut-être des commentaires conditionnels, je ne suis pas sûr. (Il a travaillé quand j'ai utilisé quelques pages simples...)

Ligne de fond est: vous ne devriez pas avoir à le faire, mais si il n'y a rien que vous pouvez faire (comme retourner une chaîne d'url), le code ci-dessus peut fonctionner.

5voto

Eli Grey Points 17553

C'est vraiment facile si la réponse est 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);
 

4voto

nickb Points 37850

Etant donné que la demande est pour une mise à jour de la réponse, voici ma solution à l'aide de HTML5 de l' Histoire de l'API avec jQuery. Il doit s'exécuter facilement en combinant le PHP et HTML parties en un seul fichier.

Ma solution permet d'AJAX pour retourner les éléments suivants:

  1. Un message par le biais de l'AJAX, ce qui met à jour un <div> conteneur.
  2. Un URL, ce qui provoque le navigateur pour rediriger vers l'URL
  3. Complet de la page HTML qui appelle l'API de l'Histoire de l' history.pushState() ajouter l'URL en cours à l'historique du navigateur et remplace l'ensemble de l'HTML de la page avec le code HTML renvoyé de l'AJAX.

PHP

Ceci est juste un échantillon de ce que le script PHP devrez retourner lorsqu'il est appelé par AJAX. Il montre comment encoder les drapeaux afin de déterminer si l'appel AJAX devrait mettre à jour le conteneur ou de charger une nouvelle page, et comment renvoyer son résultat via JSON par json_encode. Pour être complet, 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

Depuis que je suis à l'aide de jQuery, permet de commencer avec ça. La suite présente un AJAX POST au serveur, au-dessus de script PHP à l'adresse URL test.php. Notez qu'il définit également le paramètre POST ajax être true, permettant le script PHP pour détecter qu'il a reçu une requête AJAX. L' dataType champ indique jQuery que la réponse du serveur sera en JSON, et qu'il doit décoder que JSON d'un objet JSON dans la réponse de rappel. Enfin, l' success de rappel, qui est déclenché lorsque l'AJAX réponse est reçue avec succès, détermine sur la base des indicateurs envoyés à partir du 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 le source HTML complète de mes testé fichier. Je l'ai testé dans FF4 - FF8. Notez que jQuery fournit l' ready méthode pour empêcher le JS de l'exécution jusqu'à ce que le DOM est chargé. J'ai aussi utilisé Google hébergement de jQuery, vous n'avez pas besoin de télécharger une copie de jQuery pour votre serveur pour tester 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>

0voto

aSeptik Points 19103

comme T-Taureau dire... l'ensemble du processus est mal ici....

vous ne sont tout simplement plus de-de compliquer les choses et vous savez que enfaite:

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 le client rediriger, puis remplissage de la nouvelle page sur le serveur.

arrêter de compliquer et de commencer à le faire bien...

  1. Client, ouvrez la page première fois, donc, la piste c' $_SESSION['tmp_client_id'] = 'client_'.session_id(); est évidemment mieux si le client est déjà inscrit, de toute façon, mettre des choses dans la table temporaire OU dans une autre session var etc...
  2. Client de remplir le formulaire;
  3. Client de soumettre le formulaire;
  4. Faire la requête AJAX;
  5. Stocker $_POST variable à l'intérieur d' tmp_client_tbl avec elle est unique, tmp_client_id OU juste $_SESSION['client_'.session_id()] = json_encode($_POST);
  6. Résultat n ° 1 ? affichage d'un message dans un </div>
  7. Conclusion n ° 2 ? actualisation de la page et cochez if( isset($_SESSION['client_'.session_id()])) { si donc, nous allons afficher à nouveau le formulaire avec les champs remplis: } else { d'affichage de 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' />" } dans une façon ninja qui suppose que vous avez ce genre de générateur de formulaire tableau où $form = array('text' => array('name','lastname'), 'select' => array('countries'), ... ), OU simplement en <input name='lastname' value='{$lastname}' /> où les valeurs sont pré-polutated avec vide vars;
  11. le temps écoulé, erreur s'est produite, navigateur fermé? session_destroy(); ou unset($_SESSION['client_'.session_id()]);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X