Persiste le variabili tra i caricamenti della pagina


95

Sto cercando di catturare la pressione del pulsante di invio del mio modulo e se il modulo viene inviato, la pagina si aggiorna e mostro alcuni campi nascosti. Vorrei catturare se il modulo è stato inviato in precedenza o meno e se è stato inviato durante il ricaricamento, vorrei mostrare i campi nascosti. Stavo cercando di utilizzare una variabile globale per ottenere questo risultato, tuttavia non sono riuscito a farlo funzionare correttamente.

Ecco cosa ho provato:

  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
    }
  });

Qualche suggerimento su cosa c'è di sbagliato in questo codice?


1
Non penso che questo possa essere fatto senza un qualche tipo di spazio di archiviazione. Le tue variabili JS saranno tutte pulite. Il tuo intero scopo verrà riciclato.
Dave Alperovich

Perché non metti la maggior parte della tua pagina in un "parziale" e lo aggiorni?
Dave Alperovich

Cos'è un parziale? Mi dispiace non ne sono a conoscenza.
Neophile

Hai considerato l'invio del modulo tramite ajax e la visualizzazione dei campi dopo l'invio?
dannyshaw

1
Puoi spiegare perché hai bisogno che la pagina si aggiorni? Se siamo in grado di evitarlo, si può in grado di fare quello che vuoi se solo preventDefaultsul submitevento (al posto del clicksi sta utilizzando.)
Peleg

Risposte:


202

Poiché HTTP è senza stato, ogni volta che carichi la pagina utilizzerà i valori iniziali di qualsiasi cosa tu abbia impostato in JavaScript. Non è possibile impostare una variabile globale in JS e semplicemente mantenere quel valore dopo aver caricato di nuovo la pagina.

Ci sono un paio di modi in cui puoi memorizzare il valore in un altro posto in modo da poterlo inizializzare al caricamento utilizzando JavaScript


Stringa della domanda

Quando si invia un modulo utilizzando il GETmetodo, l'URL viene aggiornato con una stringa di query ( ?parameter=value&something=42). È possibile utilizzarlo impostando un campo di input nel modulo su un determinato valore. Questo sarebbe l'esempio più semplice:

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

Al caricamento iniziale della pagina, non viene impostata alcuna stringa di query. Quando si invia questo modulo, la namee la valuecombinazione dell'input vengono passati nella stringa di query come clicked=true. Quindi, quando la pagina viene caricata di nuovo con quella stringa di query, puoi verificare se il pulsante è stato cliccato.

Per leggere questi dati, è possibile utilizzare il seguente script al caricamento della pagina:

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');

( Fonte )

La capacità di utilizzarlo dipende da come funziona attualmente il modulo, se utilizzi già un POST, questo potrebbe essere problematico.

Inoltre, per set di dati più grandi questo è meno che ottimale. Il passaggio di una stringa non è un grosso problema, ma per gli array e gli oggetti di dati dovresti probabilmente usare Web Storage o cookie. Sebbene i dettagli differiscano leggermente tra i browser, il limite pratico alla lunghezza dell'URI è di circa 2000 caratteri


Archiviazione web

Con l'introduzione di HTML5 abbiamo anche lo storage Web, che ti consente di salvare le informazioni nel browser durante i caricamenti delle pagine. C'è localStorageche può salvare i dati per un periodo più lungo (a condizione che l'utente non li cancelli manualmente) e sessionStorageche salva i dati solo durante la sessione di navigazione corrente. Quest'ultimo ti è utile qui, perché non vuoi mantenere "cliccato" impostato su true quando l'utente torna più tardi.

Qui ho impostato l'archiviazione sull'evento clic del pulsante, ma potresti anche vincolarlo al modulo di invio o qualsiasi altra cosa.

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

Quindi, quando carichi la pagina, puoi verificare se è impostato usando questo:

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

Anche se questo valore viene salvato solo durante questa sessione di navigazione, potrebbe essere possibile ripristinarlo prima. Per farlo, usa:

sessionStorage.removeItem('clicked');

Se vuoi salvare un oggetto o un array JS devi convertirlo in una stringa. Secondo le specifiche dovrebbe essere possibile salvare altri tipi di dati, ma questo non è ancora implementato correttamente nei browser.

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

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

Il supporto del browser è piuttosto eccezionale, quindi dovresti essere sicuro di usarlo a meno che non sia necessario supportare browser molto vecchi / oscuri. Il Web Storage è il futuro.


Biscotti

Un'alternativa al Web Storage è il salvataggio dei dati in un cookie. I cookie sono realizzati principalmente per leggere i dati lato server, ma possono essere utilizzati anche per dati puramente lato client.

Utilizzi già jQuery, il che semplifica l'impostazione dei cookie. Ancora una volta, utilizzo l' clickevento qui ma potrebbe essere utilizzato ovunque.

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

Quindi al caricamento della pagina puoi leggere il cookie in questo modo:

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

Poiché i cookie persistono tra le sessioni nel tuo caso, dovrai disattivarli non appena hai fatto tutto ciò che devi fare con esso. Non vorresti che l'utente torni un giorno dopo e che sia ancora clickedimpostato su true.

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

(un modo non jQuery per impostare / leggere i cookie può essere trovato proprio qui )

Personalmente non userei un cookie per qualcosa di semplice come ricordare uno stato cliccato, ma se la stringa di query non è un'opzione ed è necessario supportare browser molto vecchi che non supportano sessionStorage questo funzionerà. Dovresti implementarlo prima con un controllo per sessionStorage e solo se fallisce usa il metodo cookie.


window.name

Sebbene questo mi sembri un trucco che probabilmente ha avuto origine prima di localStorage / sessionStorage, potresti memorizzare le informazioni nella window.nameproprietà:

window.name = "my value"

Può memorizzare solo stringhe, quindi se vuoi salvare un oggetto dovrai stringerlo proprio come localStoragenell'esempio sopra :

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

La differenza principale è che queste informazioni vengono conservate non solo negli aggiornamenti della pagina ma anche in domini diversi. Tuttavia, è limitato alla scheda corrente in cui ti trovi.

Ciò significa che potresti salvare alcune informazioni sulla tua pagina e finché l'utente rimane in quella scheda, potresti accedere a quelle stesse informazioni anche se ha navigato su un altro sito Web e viceversa. In generale, consiglierei di non utilizzarlo a meno che non sia necessario memorizzare effettivamente le informazioni interdominio durante una singola sessione di navigazione.


9
Uffa, solo dopo aver scritto ho letto la tua descrizione della taglia che diceva "no cookies o local storage". Terrò intatto questo commento per gli altri che potrebbero averne bisogno, ma immagino che dovrai solo usare la stringa di query.
Stephan Muller

1
Fondamentalmente sto già utilizzando localStorage in molti casi per la mia applicazione web e vorrei evitare di utilizzare troppe variabili localStorage. Tuttavia mi piace l'idea di rimuovere l'elemento localStorage una volta che ho finito con esso. Era qualcosa a cui non pensavo quando utilizzavo la mia variabile localStorage.
Neofilo

3
In caso di richiesta di post puoi modificare l'azione -attribute $ ("# formid"). Attr ("action", url + "& clicked = 1") e anche rilevare GET o POST da $ ("# formid"). Attr ( "metodo") ma potrebbe non risolvere come rilevare il problema di ricarica
Tero Tolonen

2
@TheNewbie è passato un po 'di tempo da quando ho scritto questa risposta, ma ho appena aggiunto una nuova opzione ( window.name). Potrebbe semplicemente fare esattamente ciò di cui hai bisogno senza usare cookies / localStorage.
Stephan Muller

1
Volevo aggiungere che l'archiviazione locale e di sessione non sono totalmente affidabili anche sui browser più recenti. Di solito c'è un fallback a window.name.
JavaScript

5

Prova a utilizzare $.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>


1

Usare localeStorageo sessionStoragesembra essere la soluzione migliore.

Per salvare la clickedvariabile nell'ambito globle, memorizzala in questo modo:

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
    }

});

Ho intenzione di non utilizzare preferibilmente localstorage o sessionStorage.
Neofilo

-5

Potresti provare questo:

 $("input[type='submit'][value='Search']").click(function(){
     form.act.value='detailSearch'; 
     clicked = true;  
     return true;
});

Quando la pagina viene ricaricata, il valore selezionato viene comunque visualizzato come falso.
Neofilo

1
@TheNewbie pensi di poter passare una stringa di query? con l'aggiornamento della pagina l'approccio corrente non funzionerà.
renakre
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.