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

AJAX Discussion :

Sauvegarde automatique de formulaire


Sujet :

AJAX

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut Sauvegarde automatique de formulaire
    Bonjour à tous,

    Je voudrais enregistrer automatiquement un formulaire en quittant ma page.
    Je ne crois pas ou je n'ai pas trouvé d’événement qui détecte le déchargement de la page avant le chargement de la suivante.
    En alternative, j'ai trouvé des infos pour l'enregistrement de chaque champ en quittant le champ (blur) mais ces techniques utilisent Ajax. Là se pose deux problèmes: Je ne connais pas Ajax et d'après ce que j'ai lu, Ajax permet d'enregistrer en XML mais moi, je voudrais enregistrer directement en base de données.
    Suis-je assez clair?

  2. #2
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Bonjour !
    Ta question est assez claire, je crois avoir compris. Un éclaircissement à propos d’ajax :
    Citation Envoyé par moimp Voir le message
    d'après ce que j'ai lu, Ajax permet d'enregistrer en XML mais moi, je voudrais enregistrer directement en base de données.
    Alors effectivement le X de ajax veut dire XML, mais c’est juste un nom et ça n’a plus tellement de sens aujourd’hui. Ce qu’il faut retenir de ajax c’est surtout qu’il permet de faire des requêtes HTTP depuis un script. XMLHttpRequest aurait pu s’appeler simplement HttpRequest, mais bon voilà c’est comme ça.

    Ton cas est d’ailleurs un des rares cas où il est légitime de faire une requête synchrone. D’habitude, les requêtes synchrones sont déconseillées car elles bloquent le fil d’exécution de la page et la rendent inerte le temps que la réponse arrive, ce qui peut donner l’impression que le navigateur a gelé.

    Mais dans ton cas, si tu agis sur l’évènement unload, ton script dit au navigateur « attends, ne ferme pas la page tout de suite, fais cette requête d’abord ». C’est un vieille technique, voici un article qui en parle et qui date de 2008 : Don’t Let the Door hit you onunload. C’est toujours d’actualité (et les bugs d’Opera ont été corrigés depuis).

    Voici un squelette de script :
    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
    window.addEventListener("unload", function () {
      "use strict"; // voir https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Strict_mode
     
      const req = new XMLHttpRequest();
      req.open(
        "POST",  // en général, on préfère POST pour envoyer des données au serveur
        "...",   // l’URL du script serveur
        false    // il faut passer explicitement false pour que la requête soit synchrone
      );
     
      // le type MIME sous lequel tu vas envoyer les donnés
      // ex. "application/json" ou "application/x-www-form-urlencoded"
      req.setRequestHeader("Content-Type", "...");
     
      // préparation des données, par exemple avec JSON.stringify()
      const data = ... ;
     
      // envoi
      req.send(data);
    });
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  3. #3
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 176
    Points
    17 176
    Par défaut
    Salut
    je n'ai pas trouvé d’événement qui détecte le déchargement de la page avant le chargement de la suivante.
    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    <body onbeforeunload="return verifmodif()">
    dans la procédure verifmodif tu y mets le code d'enregistrement automatiquement du formulaire.
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Merci pour vos réponses.
    @ProgElecT: Oui mais je préfère mettre un écouteur et traiter les contrôles en PHP.
    @Watilin:
    Merci pour ces explications qui me permettent de mieux comprendre, mais malheureusement pas tout.
    1-Je place toujours un "use strict" en début de tous mes scripts php, ce qui m'évite bien des déboires, en particulier à la mise au point.
    2-Si c'est possible, je préférerais ne pas passer par Ajax mais simplement soumettre mon formulaire et accéder à mon script de contrôle en php. Malheureusement, la soumission du formulaire provoque une erreur 'non spécifiée' à la ligne 5 dans le débogueur de IE.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	window.addEventListener('unload', function(e)
    	{
    		alert('xxxxx');
    		console.log(cardForm.action);
    		cardForm.submit();
    	}, false );
    3-Dans ton code, je ne comprends pas tout:
    Ligne 7: de quel URL s'agit-il? Je suppose que c'est celui qui traite les contrôles et effectue l'enregistrement en base de données.
    Lignes 11 et suivante: Pourquoi faut-il préciser un type MIME et préparer (convertir?) les données. Je ne peux pas les transférer à l'état brut en texte comme elles sont codées en utf-8?

  5. #5
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Citation Envoyé par moimp Voir le message
    1-Je place toujours un "use strict" en début de tous mes scripts php
    Tes scripts PHP ? Ce n’est pas clair. Le mode strict dont je parle concerne JavaScript. J’aimerais être certain qu’on parle de la même chose :/

    Citation Envoyé par moimp Voir le message
    2-Si c'est possible, je préférerais ne pas passer par Ajax mais simplement soumettre mon formulaire et accéder à mon script de contrôle en php.
    L’évènement unload survient lorsque le navigateur a déjà commencé la procédure de déchargement de la page. La page peut être déchargée de deux façons :
    • soit une nouvelle page va être chargée à la place,
    • soit la fenêtre ou l’onglet est en train d’être fermé.

    L’évènement n’est pas annulable et, dans le cas de la navigation vers une autre page, la destination ne peut pas être modifiée (c’est une mesure de sécurité). Ainsi, il n’est pas possible de demander la soumission du formulaire à ce moment-là, car ça changerait la destination.

    Tout ce processus se passe côté client et le serveur ne peut avoir aucune influence dessus. C’est pourquoi on a besoin de JavaScript, et avec JavaScript, la seule opération bloquante qui permet de retarder le déchargement de la page, c’est une requête « ajax » synchrone.

    Citation Envoyé par moimp Voir le message
    Malheureusement, la soumission du formulaire provoque une erreur 'non spécifiée' à la ligne 5 dans le débogueur de IE.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	window.addEventListener('unload', function(e)
    	{
    		alert('xxxxx');
    		console.log(cardForm.action);
    		cardForm.submit();
    	}, false );
    Un débogueur qui fait des messages d’erreur aussi peu utiles ne mérite que notre dédain. Tu as quoi comme message d’erreur sous Firefox ou Chrome par exemple ?
    Note que, comme documenté sur la page MDN de unload, une partie des ressources de la page et des API du navigateur ne sont plus disponibles, notamment alert().

    Citation Envoyé par moimp Voir le message
    3-Dans ton code, je ne comprends pas tout:
    Ligne 7: de quel URL s'agit-il? Je suppose que c'est celui qui traite les contrôles et effectue l'enregistrement en base de données.
    Oui. C’est la même URL que l’attribut action de ton formulaire.
    Citation Envoyé par moimp Voir le message
    Lignes 11 et suivante: Pourquoi faut-il préciser un type MIME et préparer (convertir?) les données. Je ne peux pas les transférer à l'état brut en texte comme elles sont codées en utf-8?
    Tu n’as pas dit comment tu envoyais tes données donc je ne pouvais pas être plus précis. Bien sûr, tu peux envoyer du texte, dans ce cas tu peux utiliser le type MIME text/plain. Côté serveur, tu accèdes aux données via l’adresse spéciale 'php://input' que tu peux utiliser avec fopen(), file_get_contents() ou similaires. (Quelques petites infos en plus dans cette doc.)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      req.setRequestHeader("Content-Type", "text/plain; charset=utf-8"); // le charset est optionnel
     
      const data = "Lorem ipsum dolor machin truc";
     
      // envoi
      req.send(data);
    Si tu préfères utiliser des paires clé-valeur dans le tableau $_POST comme d’habitude, tu dois utiliser le type application/x-www-form-urlencoded et envoyer une chaîne clé1=valeur1&clé2=valeur2&... (comme avec la méthode GET). Il est conseillé d’encoder les clés et les valeurs avec encodeURIComponent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
     
      const data = encodeURIComponent("clé1") + "=" + encodeURIComponent("valeur1") + "&" +
        encodeURIComponent("clé2") + "=" + encodeURIComponent("valeur2") + "&" +
        ... ;
     
      // envoi
      req.send(data);
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  6. #6
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Pour le point 1, c'est un lapsus. Il s'agit bien des scripts JavaScript.

    Pour le reste, merci pour tes explications, je vais regarder ça de plus près. Je marque le sujet comme résolu, quitte à le réactiver si nécessaire.

  7. #7
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Mon problème n'est toujours pas résolu, même si je comprends beaucoup mieux. Je n'arrive pas à préparer mes données pour les transmettre.
    Il me semble que le mieux serait de les transmettre soit:

    1. sous la forme que tu indique:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");[*] [*]  const data = encodeURIComponent("clé1") + "=" + encodeURIComponent("valeur1") + "&" +[*]    encodeURIComponent("clé2") + "=" + encodeURIComponent("valeur2") + "&" +[*]    ... ;[*]
      mais je n'arrive pas à récupérer les clefs.
      .
    2. soit sérialiser mes données en php et transmettre la chaîne sérialisée mais je me demande si c'est bien recommandé.

    Voici mon code dans son état actuel:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <script>
    	const arrPost = <?= json_encode($_POST); ?>;
    </script>
    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
    window.addEventListener("unload", function () {
     
    	const req = new XMLHttpRequest();
    	console.log(arrPost);
    	console.log(max);
    	console.log(JSON.stringify(arrPost));
     
    	req.open(
    		"POST",
    		"<?= URL_SITE; ?>frontend/controllers/addressHandle.php",
    		false
    	);
     
    	req.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
     
    	// préparation des données, par exemple avec JSON.stringify()
    	//const data = ... ;
     
    	// envoi
    	//req.send(data);
    });
    J'ai aussi essayé de transmettre séparément les clefs et les valeurs du $_POST mais je n'y arrive pas. J'obtiens toujours une erreur de variables indéfinies. Pourtant la ligne 1 me renvoie bien mon tableau $_POST correct.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <?php print_r($_POST); ?>
    <script src="<?= URL_SITE; ?>common/js/cardFrame.js"></script>
    <script>
    	const arrPostKeys	= <?= json_encode(array_keys($_POST)); ?>;
    	const arrPostValues	= <?= json_encode(array_values($_POST)); ?>;
    </script>

  8. #8
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut Envoi auto de formulaire: déboguer
    Bonjour,
    J'ai aussi repris complètement un cours et travaillé les exemples de MDN. J'ai lu la FAQ de ce site, et notamment la rubrique sur l'asynchrone sans tout comprendre (En passant, je regrette que dans cette FAQ, les dates de mise à jour ne soit pas reportées sur chaque article).

    Malheureusement, je n'arrive toujours pas à comprendre pourquoi mon code ne fonctionne pas, ce qui est est d'ailleurs rendu difficile par l'impossibilité d'utiliser la console ou la fonction alert.

    Mon application comprend une page mère avec plusieurs onglets comportant chacun un ou plusieurs formulaires identiques mais avec des données différentes.
    Prenons déjà le cas le plus simple avec un formulaire par onglet. Le clic sur un onglet (lien) recharge la page avec le formulaire correspondant à cet onglet.

    Mon but est de soumettre le formulaire lorsque je clique sur un autre onglet. Dans ce cas, l'url (targetFile dans mon code) correspond au fichier php de traitement du formulaire. Le problème est que comme je quitte la page et que la page appelée ne contient que du code php, je ne vois rien et rien ne se passe.

    J'ai essayé le code donné par Watilin dans le lien ci-dessus et le code ci-dessous mais je ne m'en sors pas:
    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
    "use strict";
     
    (function()
    {
     
    	window.addEventListener('unload', function()
    	{
    		const myForm = document.querySelector('form')
    			, myData = new FormData(myForm)
    			, req = new XMLHttpRequest()
    			, output = document.querySelector('div') // à préciser
    		;
     
    		req.open('POST', targetFile);
    		req.addEventListener('load', function(e)
    		{
    			if (req.status != 200)
    			{
    				output.innerHTML = "Problème !!";
    			}
    		}, false );
    		req.send(myData);
    	}, false );
     
    }) ();

  9. #9
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Petite mise à jour depuis la dernière fois, j’ai découvert la fonction navigator.sendBeacon() qui est précisément faite pour ton cas. C’est une requête HTTP non bloquante, qui n’est pas annulée par le déchargement de la page, et qui est plus simple à coder qu’une requête ajax. Que des avantages donc
    (On pourra toutefois objecter, si on est pessimiste, que cette fonction, vu son objectif assumé de collecte de statistiques, pourrait être à l’avenir bloquée par des extensions de protection de la vie privée. Une éventualité à surveiller.)

    Citation Envoyé par moimp Voir le message
    2. soit sérialiser mes données en php et transmettre la chaîne sérialisée mais je me demande si c'est bien recommandé.
    La sérialisation PHP est un format que JavaScript ne connaît pas. Tu pourrais coder une fonction JS qui fait ça, mais dans ce cas ça n’aurait pas d’avantage par rapport à clé1=valeur1&clé2=valeur2&… (le format 'application/x-www-form-urlencoded').

    Citation Envoyé par moimp Voir le message
    Mon problème n'est toujours pas résolu, […] Je n'arrive pas à préparer mes données pour les transmettre.
    Il me semble que le mieux serait de les transmettre soit:

    1. sous la forme que tu indique:
    […]
    mais je n'arrive pas à récupérer les clefs.[/list]
    […]
    Voici mon code dans son état actuel:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <script>
    	const arrPost = <?= json_encode($_POST); ?>;
    </script>
    […]
    J'ai aussi essayé de transmettre séparément les clefs et les valeurs du $_POST mais je n'y arrive pas. J'obtiens toujours une erreur de variables indéfinies.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <script>
    	const arrPostKeys	= <?= json_encode(array_keys($_POST)); ?>;
    	const arrPostValues	= <?= json_encode(array_values($_POST)); ?>;
    </script>
    Utilise Ctrl+U et regarde les balises <script> générées. Je ne sais pas exactement d’où vient le problème, mais PHP envoie peut-être des messages d’erreur, qui causent à leur tour des erreurs de syntaxe en JavaScript.
    As-tu des messages d’erreur dans la console ?

    Il se peut aussi que json_encode échoue silencieusement et envoie une chaîne vide. Ajoute l’option JSON_THROW_ON_ERROR si tu es sous PHP 7.3 ou plus, ou JSON_PARTIAL_OUTPUT_ON_ERROR, ou d’autres que tu jugeras utiles – voir la page des constantes JSON PHP.

    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    json_encode(array_keys($_POST), JSON_THROW_ON_ERROR);

    Tu peux également vérifier si json_last_error() renvoie quelque chose.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  10. #10
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Tout comme alert(), le DOM n’est plus disponible quand la page est en cours de déchargement. Donc innerHTML ne marche pas non plus. En revanche, console.log() est toujours accessible, le seul obstacle étant le vidage des journaux lors d’un changement de page. Heureusement il y a une option « journaux persistants » dans la console.

    J’ai posté une réponse sur ton autre fil, à peu près au même moment où tu as ouvert celui-ci, va jeter un œil
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  11. #11
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Citation Envoyé par Watilin Voir le message
    Petite mise à jour depuis la dernière fois, j’ai découvert la fonction navigator.sendBeacon() qui est précisément faite pour ton cas. C’est une requête HTTP non bloquante, qui n’est pas annulée par le déchargement de la page, et qui est plus simple à coder qu’une requête ajax. Que des avantages donc
    (On pourra toutefois objecter, si on est pessimiste, que cette fonction, vu son objectif assumé de collecte de statistiques, pourrait être à l’avenir bloquée par des extensions de protection de la vie privée. Une éventualité à surveiller.)
    En plus de la raison que tu évoques, cette fonction ne fonctionne pas sur tous les navigateurs.

    Dans l'exemple que tu as donné sur l'autre fil, pourquoi as-tu mis le troisième paramètre à false (=synchrone) ?

    Pour le reste, mon code est directement tiré d'un exemple de MDN à une différence près mais une différence de taille: l'événement déclencheur. Si j'affiche le formulaire dans la console, l'élément form est bien visible, mais il est vide.

  12. #12
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Tout ça c’est des choses qui ont déjà été dites. Mais je vais résumer.

    Lorsque ton code réagit à un évènement unload, la page est dans un état spécial. Le déchargement est déjà initié et ne peut pas être annulé (contrairement à beforeunload). Certaines choses ne sont plus accessibles, notamment l’API graphique (alert, confirm, etc.) et le DOM. Je rappelle que le DOM est la représentation structurée des éléments HTML de la page. Le formulaire fait partie du DOM.

    Une requête ajax, par défaut, est asynchrone. Problème : lorsqu’une page est complètement déchargée, son contexte d’exécution JavaScript est détruit, toute requête ajax qui s’y faisait est alors annulée. L’évènement unload te permet d’initier des requêtes asynchrone, mais ne donne pas de garantie que la requête aura le temps de se faire avant la destruction du contexte.
    En faisant une requête synchrone, tu bloques le fil d’exécution et tu retardes la destruction du contexte JavaScript de la page. La contrepartie, c’est que la page est gelée pendant ce temps, et l’utilisateur peut avoir l’impression que son navigateur a planté.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  13. #13
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Premièrement, j'ai modifié ma façon d'envoyer mes données. Je les envoie sous forme d'un objet json et non plus en les lisant directement à partir du formulaire. Ces données sont maintenant correctes.
    Effectivement, en rendant la requête synchrone, readystate passe de 1 à 4 et le statut passe à 200.
    Il me reste un problème que je ne sais pas comment traiter: Comment ou plutôt où faire mes contrôles de saisie et l'enregistrement des données? En effet, j'ai mis un fichier de traitement des données comme cible mais c'est la page demandée par l'utilisateur qui s'affiche.

  14. #14
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Il y a deux sortes de contrôle de saisie : celui qu’on fait côté client, pour le confort de l’utilisateur, et celui qu’on fait côté serveur pour la sécurité.

    Le contrôle client, tu ne peux pas le faire pendant unload, il faudrait donc que tu le fasses avant, pendant la saisie par exemple. Voir l’évènement input.

    Le contrôle serveur, tu dois le faire dans le code serveur qui reçoit la requête synchrone. Comme je l’ai déjà dit, tu ne peux pas modifier « l’action de navigation » qui a provoqué l’évènement unload. Une action de navigation, ça peut être :
    • un clic sur un lien ;
    • une soumission de formulaire ;
    • une redirection <meta> (désuet) ou via JavaScript avec l’objet location ;
    • un truc externe à la page, par exemple l’utilisateur clique sur un marque-page.

    Au moment du unload, ton serveur peut envoyer une réponse à la requête synchrone, mais le JavaScript ne peut plus adresser de message à l’utilisateur. Ce que tu peux faire à ce moment, c’est stocker l’information voulue dans le localStorage et l’afficher à la page suivante. Mais cela suppose que la page suivante a le code JavaScript prévu pour ça.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  15. #15
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Merci. J'ai appris et compris beaucoup de choses. Chaque fois que je change d'onglet, je recharge le formulaire avec le sessionStorage (je préfère au localStorage). Maintenant lorsque toutes mes pages sont à jour, comment est-ce que je fais pour transmettre toutes les données au serveur, vu que ma variable $_POST ne conserve que le dernier onglet et que j'ai 8 onglets avec 8 formulaires ou groupes de formulaires d'une vingtaine de champs chacun.

  16. #16
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    ma variable $_POST ne conserve que le dernier onglet
    C’est normal : le serveur traite chaque requête HTTP dans une instance différente de ton script PHP. Pour simplifier (même si ce n’est pas tout à fait vrai), on pourrait dire que le serveur traite chaque requête dans un processus différent.

    Pour conserver les données $_POST tu es obligé de les sauvegarder dans $_SESSION (sans oublier de les nettoyer avant). Tu peux, par exemple, organiser tout ça avec des timestamps (fournis par time()) qui te serviront de clés dans un tableau associatif.
    Code PHP : 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
    <?php
    if (!session_id()) {
        session_start();
    }
     
    // l’opérateur “??” permet de se passer de isset()
    $id = $_POST['id'] ?? '-1';
    $id = intval($id);
     
    // idem avec les autres valeurs $_POST
    // ...
    // ...
    // ...
     
    $timestamp = time();
    $_SESSION['postdata'][$timestamp] = [
      'id' => $id,
      // ...
    ];

    Ensuite tu retrouves toutes les données dans $_SESSION['postdata'], et tu peux les trier par timestamp avec ksort() par exemple.
    Le code devra aussi supprimer les données quand il n’en as plus besoin.

    C’est peut-être pas la plus simple des solutions, mais sur le moment, je n’ai pas d’autre idée
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  17. #17
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Je me suis mal exprimé. Tout ceci, je le maîtrise. Ce que je ne maîtrise pas se situe en amont: Comment dois-je récupérer les données transmises côté serveur dans le fichier cible, justement pour pouvoir les contrôler et les enregistrer. J'ai d'ailleurs une ambiguïté sur la cible puisque je donne un fichier cible target='cardFrame.php' et que l'utilisateur a cliqué sur un lien du type 'cardFrame.php?tab=n.'
    Si en tête du fichier cible (cardFrame.php), je fais un print_r($_POST), je devrais recevoir les données, non? Or le print_r me renvoie un tableau vide.
    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
    	window.addEventListener('unload', function()
    	{
    		const myData	= new FormData(arrPostData)
    			, req		= new XMLHttpRequest()
    			, output	= document.querySelector('.displResult')
    		;
     
    		req.open('POST', targetFile, false); // targetFile est une variable transmise par PHP et qui vaut 'cardFrame.php'
    		req.addEventListener('load', function(e)
    		{
    			if (req.status != 200)
    			{
    				output.innerHTML = "Problème !!";
    			}
    			else { output.innerHTML = "ok OK OK"; }
    		}, false );
    		req.send(myData);
    		console.log(targetFile);  // retourne 'cardFrame.php'
    		console.log(arrPostData); // retourne correctement les données du formulaire qu'on quitte
    		console.log(window.location); // Retourne URL + 'cardFrame.php?tab=n' avec n = un entier correspondant à l'onglet (au formulaire) qu'on quitte
    	}, false );

  18. #18
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    XMLHttpRequest ne sait pas sur quoi l’utilisateur a cliqué, et l’adresse passée à .open peut être n’importe quoi, il n’y a pas de rapport avec l’adresse de la page (à part le fait que c’est un chemin relatif).

    Pour être bien clair : le navigateur fait deux requêtes en même temps, à deux adresses distinctes :
    • celle initiée par le clic de l’utilisateur, qui demande la nouvelle page ;
    • celle faite par XMLHttpRequest, à l’adresse que toi tu lui as passée.


    Dans ton code, il y a deux problèmes :
    1. Comme la requête est synchrone, tu ne peux pas utiliser le gestionnaire de "load". Écris simplement le code de gestion de la réponse à la suite de .send().
    2. Tu ne peux pas utiliser innerHTML car le DOM n’existe plus. C’est précisément pour cette raison que je t’ai proposé d’utiliser localStorage, ce à quoi tu as répondu que tu préférais sessionStorage.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  19. #19
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Citation Envoyé par Watilin Voir le message
    XMLHttpRequest ne sait pas sur quoi l’utilisateur a cliqué, et l’adresse passée à .open peut être n’importe quoi, il n’y a pas de rapport avec l’adresse de la page (à part le fait que c’est un chemin relatif).Pour être bien clair : le navigateur fait deux requêtes en même temps, à deux adresses distinctes :
    • celle initiée par le clic de l’utilisateur, qui demande la nouvelle page ;
    • celle faite par XMLHttpRequest, à l’adresse que toi tu lui as passée.
    C'est ce que j'avais cru comprendre au départ, mais du fait que j'utilise l'événement .unload, je me sentais obligé de prendre la même adresse.

    Citation Envoyé par Watilin Voir le message
    Dans ton code, il y a deux problèmes :
    1. Comme la requête est synchrone, tu ne peux pas utiliser le gestionnaire de "load". ...
    2. Tu ne peux pas utiliser innerHTML car le DOM n’existe plus. ...
    Ce n'est pas grave, car j'avais repris ce code d'un exemple, en attendant de voir si j'en aurais besoin. J'ai donc effacer cette partie de code.

    Citation Envoyé par Watilin Voir le message
    Écris simplement le code de gestion de la réponse à la suite de .send(). C’est précisément pour cette raison que je t’ai proposé d’utiliser localStorage, ce à quoi tu as répondu que tu préférais sessionStorage.
    C'est précisément là que je coince depuis un bon bout de temps. Ce n'est pas la gestion des données en JavaScript qui me gène, c'est l'appel au traitement PHP et la transmission des données à ce traitement PHP. Est-ce que ça signifie que le code de traitement se déroule parallèlement à la page affichée? J'ai essayé d'incorporer ce traitement dans la page appelée par l'utilisateur ou d'appeler une page spécifique pour le traitement. Dans les deux cas si j'effectue un print_r($_POST) , j'obtiens un tableau vide et dans le deuxième cas ma page n'est pas appelée. Autrement dit comment faut-il que j'appelle la page PHP de traitement en lui envoyant les données du formulaire?

  20. #20
    Membre éclairé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 579
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 579
    Points : 804
    Points
    804
    Par défaut
    Je ne comprends pas ce qui ne va pas dans mon code. Je résume la situation.
    L'utilisateur clique sur un lien vers une page quelconque.
    Il déclenche l'écouteur sur l'événement unload de window et donc la procédure AJAX de façon SYNCHRONE.
    Cette procédure envoie les données au fichier 'cardFrameHandle.php' mais celui-ci ne s'ouvre pas.

    Contenu du fichier de destination 'cardFrameHandle.php'
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <?php
    var_dump($_POST);echo '<br/>';
    ?>
    <script>alert('cccccc');</script>

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Débutant] sauvegarde automatique d'un formulaire sous format pdf
    Par ahmed_kh dans le forum VB.NET
    Réponses: 1
    Dernier message: 01/07/2012, 10h55
  2. Réponses: 1
    Dernier message: 10/04/2012, 16h57
  3. [Prototype] Sauvegarde automatique d'un formulaire
    Par Higestromm dans le forum Bibliothèques & Frameworks
    Réponses: 0
    Dernier message: 03/03/2009, 15h49
  4. [AJAX] sauvegarde automatique d'un champ d'un formulaire
    Par LuneArgentee dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 22/04/2008, 13h41
  5. sauvegarde automatique
    Par bourvil dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 18/11/2003, 14h13

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