Persistance des variables entre les chargements de page

95

J'essaie de capturer le bouton d'envoi de mon formulaire et si le formulaire est soumis, la page s'actualise et j'affiche quelques champs cachés. Je voudrais savoir si le formulaire a déjà été soumis ou non et s'il a été soumis lors du rechargement, je voudrais afficher les champs masqués. J'essayais d'utiliser une variable globale pour y parvenir, mais je n'ai pas pu le faire fonctionner correctement.

Voici ce que j'ai essayé:

  var clicked = false;

  $(document).ready(function() {

    $("input[type='submit'][value='Search']").attr("onclick", "form.act.value='detailSearch'; clicked = true;  return true;");

    if (clicked == true) {
      // show hidden fields
    } else {
      // don't show hidden fields
    }
  });

Des suggestions sur ce qui ne va pas avec ce code?

Néophile
la source
1
Je ne pense pas que cela puisse être fait sans une sorte de stockage. Vos variables JS seront toutes nettoyées. Toute votre lunette sera recyclée.
Dave Alperovich
Pourquoi ne pas mettre la majeure partie de votre page dans un "partiel" et actualiser cela?
Dave Alperovich
Qu'est-ce qu'un partiel? Désolé, je ne suis pas au courant de cela.
Neophile
Avez-vous envisagé de soumettre le formulaire via ajax et d'afficher les champs après la soumission?
dannyshaw
1
Pouvez-vous expliquer pourquoi vous avez besoin d'actualiser la page? Si nous pouvons l'éviter, vous pourrez peut-être faire ce que vous voulez si vous vous contentez preventDefaultde l' submitévénement (au lieu de celui clickque vous utilisez.)
Peleg

Réponses:

202

Comme HTTP est sans état, chaque fois que vous chargez la page, il utilisera les valeurs initiales de tout ce que vous avez défini dans JavaScript. Vous ne pouvez pas définir une variable globale dans JS et simplement faire en sorte que cette valeur reste après le chargement de la page à nouveau.

Il existe plusieurs façons de stocker la valeur à un autre endroit afin de pouvoir l'initialiser au chargement à l'aide de JavaScript


Chaîne de requête

Lors de la soumission d'un formulaire à l'aide de la GETméthode, l'url est mise à jour avec une chaîne de requête ( ?parameter=value&something=42). Vous pouvez l'utiliser en définissant un champ de saisie dans le formulaire sur une certaine valeur. Ce serait l'exemple le plus simple:

<form method="GET">
    <input type="hidden" name="clicked" value="true" />
    <input type="submit" />
</form>

Lors du chargement initial de la page, aucune chaîne de requête n'est définie. Lorsque vous soumettez ce formulaire, la combinaison nameet valuede l'entrée est transmise dans la chaîne de requête sous la forme clicked=true. Ainsi, lorsque la page se charge à nouveau avec cette chaîne de requête, vous pouvez vérifier si le bouton a été cliqué.

Pour lire ces données, vous pouvez utiliser le script suivant lors du chargement de la page:

function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

var clicked = getParameterByName('clicked');

( Source )

La possibilité d'utiliser cela dépend de la façon dont votre formulaire fonctionne actuellement, si vous utilisez déjà un POST, cela pourrait être problématique.

En outre, pour des ensembles de données plus volumineux, ce n'est pas optimal. Faire passer une chaîne n'est pas un gros problème, mais pour les tableaux et les objets de données, vous devriez probablement utiliser le stockage Web ou des cookies. Bien que les détails diffèrent un peu selon les navigateurs, la limite pratique de la longueur de l'URI est d'environ 2000 caractères


Espace archivage sur le Web

Avec l'introduction de HTML5, nous avons également obtenu le stockage Web, qui vous permet d'enregistrer des informations dans le navigateur à travers les chargements de page. Il existe un système localStoragequi peut enregistrer des données pendant une période plus longue (tant que l'utilisateur ne les efface pas manuellement) et sessionStoragequi enregistre les données uniquement pendant votre session de navigation en cours. Ce dernier est utile pour vous ici, car vous ne voulez pas garder "cliqué" sur true lorsque l'utilisateur revient plus tard.

Ici, j'ai défini le stockage sur l'événement de clic sur le bouton, mais vous pouvez également le lier à l'envoi de formulaire ou à toute autre chose.

$('input[type="submit"][value="Search"]').click(function() {
    sessionStorage.setItem('clicked', 'true');
});

Ensuite, lorsque vous chargez la page, vous pouvez vérifier si elle est définie en utilisant ceci:

var clicked = sessionStorage.getItem('clicked');

Même si cette valeur n'est enregistrée que pendant cette session de navigation, il est possible que vous souhaitiez la réinitialiser plus tôt. Pour ce faire, utilisez:

sessionStorage.removeItem('clicked');

Si vous souhaitez enregistrer un objet ou un tableau JS, vous devez le convertir en chaîne. Selon les spécifications, il devrait être possible d'enregistrer d'autres types de données, mais cela n'est pas encore correctement implémenté dans les navigateurs.

//set
localStorage.setItem('myObject', JSON.stringify(myObject));

//get
var myObject = JSON.parse(localStorage.getItem('myObject'));

La prise en charge des navigateurs est assez bonne , vous devriez donc l'utiliser en toute sécurité, sauf si vous avez besoin de prendre en charge des navigateurs vraiment anciens / obscurs. Le stockage Web est l'avenir.


Biscuits

Une alternative au stockage Web consiste à enregistrer les données dans un cookie. Les cookies sont principalement conçus pour lire les données côté serveur, mais peuvent également être utilisés pour des données purement côté client.

Vous utilisez déjà jQuery, ce qui facilite la configuration des cookies. Encore une fois, j'utilise l' clickévénement ici mais pourrait être utilisé n'importe où.

$('input[type="submit"][value="Search"]').click(function() {
    $.cookie('clicked', 'true', {expires: 1}); // expires in 1 day
});

Ensuite, lors du chargement de la page, vous pouvez lire le cookie comme ceci:

var clicked = $.cookie('clicked');

Comme les cookies persistent à travers les sessions dans votre cas, vous devrez les désactiver dès que vous avez fait tout ce que vous devez faire avec. Vous ne voudriez pas que l'utilisateur revienne un jour plus tard et qu'il soit toujours clickeddéfini sur true.

if(clicked === "true") {
    //doYourStuff();
    $.cookie('clicked', null);
}

(un moyen non-jQuery de définir / lire les cookies peut être trouvé ici )

Personnellement, je n'utiliserais pas de cookie pour quelque chose de simple comme se souvenir d'un état cliqué, mais si la chaîne de requête n'est pas une option et que vous devez prendre en charge les navigateurs vraiment anciens qui ne prennent pas en charge sessionStorage, cela fonctionnera. Vous devez implémenter cela avec une vérification de sessionStorage en premier, et seulement si cela échoue, utilisez la méthode des cookies.


window.name

Bien que cela me semble être un hack qui provient probablement d'avant localStorage / sessionStorage, vous pouvez stocker des informations dans la window.namepropriété:

window.name = "my value"

Il ne peut stocker que des chaînes, donc si vous souhaitez enregistrer un objet, vous devrez le stringifier comme dans l' localStorageexemple ci-dessus :

window.name = JSON.stringify({ clicked: true });

La principale différence est que ces informations sont conservées non seulement dans les actualisations de page, mais également dans différents domaines. Cependant, il est limité à l'onglet actuel dans lequel vous vous trouvez.

Cela signifie que vous pouvez enregistrer certaines informations sur votre page et tant que l'utilisateur reste dans cet onglet, vous pouvez accéder à ces mêmes informations même s'il a navigué sur un autre site Web et inversement. En général, je déconseille de l'utiliser à moins que vous n'ayez réellement besoin de stocker des informations inter-domaines au cours d'une seule session de navigation.

Stéphan Muller
la source
9
Ugh, ce n'est qu'après avoir écrit que j'ai lu la description de votre prime qui disait "pas de cookies ni de stockage local". Je garderai ce commentaire intact pour les autres qui pourraient en avoir besoin, mais vous devrez simplement utiliser la chaîne de requête, je suppose.
Stephan Muller
1
En gros, j'utilise déjà localStorage dans de nombreux cas pour mon application Web et je voudrais éviter d'utiliser trop de variables localStorage. Cependant, j'aime l'idée de supprimer l'élément localStorage une fois que j'en ai terminé avec lui. C'est quelque chose auquel je n'ai pas pensé lors de l'utilisation de ma variable localStorage.
Neophile
3
En cas de demande de publication, vous pouvez modifier l'action -attribute $ ("# formid"). Attr ("action", url + "& clicked = 1") et aussi détecter GET ou POST à ​​partir de $ ("# formid"). Attr ( "method") mais il ne résoudra peut-être pas comment détecter le problème de rechargement
Tero Tolonen
2
@TheNewbie ça fait un moment que j'ai écrit cette réponse, mais je viens d'ajouter une nouvelle option ( window.name). Il peut simplement faire exactement ce dont vous avez besoin sans utiliser les cookies / localStorage.
Stephan Muller
1
Je voulais ajouter que le stockage local et de session ne sont pas totalement fiables sur les nouveaux navigateurs également. Il existe généralement une solution de secours pour window.name.
JavaScript
5

Essayez d'utiliser $.holdReady(),history

function show() {
  return $("form input[type=hidden]")
          .replaceWith(function(i, el) {
            return "<input type=text>"
          });
}

$.holdReady(true);
    if (history.state !== null && history.state.clicked === true) {
       // show hidden fields
       // if `history.state.clicked === true` ,
       // replace `input type=hidden` with `input type=text`
       show();
       console.log(history);

    } else {
        // don't show hidden fields
        console.log(history);
    }
$.holdReady(false);

  $(document).ready(function() {

    $("input[type=submit][value=Search]")
    .on("click", function(e) {
        e.preventDefault();
        if (history.state === null) {
          // do stuff
          history.pushState({"clicked":true});
          // replace `input type=hidden` with `input type=text`
          show();
          console.log(history);
        } else {
          // do other stuff
        };
    });

  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="POST">
    <input type="text" name="name" value="" />
    <input type="submit" value="Search" />
    <input type="hidden" />
    <input type="hidden" />
</form>

invité271314
la source
1

Utiliser localeStorageou sessionStoragesemble être le meilleur pari.

Au lieu de sauvegarder la clickedvariable dans le scope globle, stockez-la de cette façon:

if(localeStorage.getItem("clicked") === null)
    localeStorage.setItem("clicked", "FALSE"); // for the first time

$(document).ready(function() {

    $("input[type='submit'][value='Search']").attr("onclick", "form.act.value='detailSearch';return true;");

    var clicked = localeStorage.getItem("clicked") == "FALSE" ? "TRUE" : "FALSE";

    localeStorage.setItem("clicked", clicked);

    if (clicked == "TRUE") {
      // show hidden fields
    } else {
      // don't show hidden fields
    }

});
me_digvijay
la source
J'ai l'intention de ne pas utiliser de préférence localstorage ou sessionStorage.
Neophile
-5

Vous pouvez essayer ceci:

 $("input[type='submit'][value='Search']").click(function(){
     form.act.value='detailSearch'; 
     clicked = true;  
     return true;
});
renakre
la source
Lorsque la page se recharge, la valeur cliquée est toujours false.
Néophile
1
@TheNewbie pensez-vous pouvoir passer une chaîne de requête? avec le rafraîchissement de la page, l'approche actuelle ne fonctionnera pas.
renakre