Variablen zwischen Seitenladevorgängen beibehalten

94

Ich versuche, den Druckknopf zum Senden meines Formulars zu erfassen. Wenn das Formular gesendet wird, wird die Seite aktualisiert und es werden einige ausgeblendete Felder angezeigt. Ich möchte erfassen, ob das Formular zuvor gesendet wurde oder nicht, und wenn es beim erneuten Laden gesendet wurde, möchte ich die ausgeblendeten Felder einblenden. Ich habe versucht, eine globale Variable zu verwenden, um dies zu erreichen, konnte sie jedoch nicht ordnungsgemäß ausführen.

Folgendes habe ich versucht:

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

Irgendwelche Vorschläge, was mit diesem Code nicht stimmt?

Neophile
quelle
1
Ich glaube nicht, dass dies ohne irgendeine Art von Speicher möglich ist. Ihre JS-Variablen werden alle sauber gepeitscht. Ihr gesamtes Zielfernrohr wird recycelt.
Dave Alperovich
Warum setzen Sie den größten Teil Ihrer Seite nicht in einen "Teil" und aktualisieren ihn?
Dave Alperovich
Was ist ein Teil? Entschuldigung, das ist mir nicht bewusst.
Neophile
Haben Sie darüber nachgedacht, das Formular über Ajax einzureichen und die Felder nach dem Absenden anzuzeigen?
Dannyshaw
1
Können Sie erläutern, warum die Seite aktualisiert werden muss? Wenn wir es vermeiden können, können Sie möglicherweise tun, was Sie wollen, wenn Sie nur preventDefaultauf der submitVeranstaltung (anstelle der, die clickSie verwenden.)
Peleg

Antworten:

201

Da HTTP zustandslos ist, werden bei jedem Laden der Seite die Anfangswerte aller in JavaScript festgelegten Elemente verwendet. Sie können in JS keine globale Variable festlegen und diesen Wert nach dem erneuten Laden der Seite einfach beibehalten.

Es gibt verschiedene Möglichkeiten, den Wert an einem anderen Ort zu speichern, damit Sie ihn beim Laden mit JavaScript initialisieren können


Abfragezeichenfolge

Beim Senden eines Formulars mit der GETMethode wird die URL mit einer Abfragezeichenfolge ( ?parameter=value&something=42) aktualisiert . Sie können dies nutzen, indem Sie ein Eingabefeld im Formular auf einen bestimmten Wert setzen. Dies wäre das einfachste Beispiel:

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

Beim ersten Laden der Seite wird keine Abfragezeichenfolge festgelegt. Wenn Sie dieses Formular senden, werden die nameund die valueKombination der Eingaben in der Abfragezeichenfolge als übergeben clicked=true. Wenn die Seite mit dieser Abfragezeichenfolge erneut geladen wird, können Sie überprüfen, ob auf die Schaltfläche geklickt wurde.

Um diese Daten zu lesen, können Sie beim Laden der Seite das folgende Skript verwenden:

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

( Quelle )

Die Fähigkeit, dies zu verwenden, hängt davon ab, wie Ihr Formular derzeit funktioniert. Wenn Sie bereits einen POST verwenden, kann dies problematisch sein.

Darüber hinaus ist dies für größere Datenmengen nicht optimal. Das Weitergeben einer Zeichenfolge ist keine große Sache, aber für Arrays und Datenobjekte sollten Sie wahrscheinlich Web Storage oder Cookies verwenden. Während sich die Details in den einzelnen Browsern geringfügig unterscheiden, liegt die praktische Grenze für die URI-Länge bei etwa 2000 Zeichen


Webspeicher

Mit der Einführung von HTML5 haben wir auch Web Storage erhalten, mit dem Sie Informationen über Seitenladungen hinweg im Browser speichern können. Es gibt localStorageDaten, die Daten für einen längeren Zeitraum speichern können (solange der Benutzer sie nicht manuell löscht) undsessionStorage die Daten nur während Ihrer aktuellen Browsersitzung speichern. Letzteres ist für Sie hier nützlich, da Sie nicht möchten, dass "angeklickt" auf "true" gesetzt bleibt, wenn der Benutzer später zurückkommt.

Hier habe ich den Speicher für das Button-Klick-Ereignis festgelegt, aber Sie können ihn auch an Submit oder etwas anderes binden.

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

Wenn Sie dann die Seite laden, können Sie überprüfen, ob sie wie folgt eingestellt ist:

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

Obwohl dieser Wert nur während dieser Browsersitzung gespeichert wird, möchten Sie ihn möglicherweise früher zurücksetzen. Verwenden Sie dazu:

sessionStorage.removeItem('clicked');

Wenn Sie ein JS-Objekt oder -Array speichern möchten, sollten Sie dies in eine Zeichenfolge konvertieren. Gemäß der Spezifikation sollte es möglich sein, andere Datentypen zu speichern, dies ist jedoch in allen Browsern noch nicht korrekt implementiert.

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

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

Die Browserunterstützung ist ziemlich gut, daher sollten Sie sicher sein, dies zu verwenden, es sei denn, Sie müssen wirklich alte / undurchsichtige Browser unterstützen. Web Storage ist die Zukunft.


Kekse

Eine Alternative zu Web Storage ist das Speichern der Daten in einem Cookie. Cookies werden hauptsächlich zum Lesen von Datenservern erstellt, können aber auch für rein clientseitige Daten verwendet werden.

Sie verwenden bereits jQuery, wodurch das Setzen von Cookies sehr einfach ist. Auch hier verwende ich das clickEreignis, kann aber überall verwendet werden.

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

Dann können Sie beim Laden der Seite den Cookie folgendermaßen lesen:

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

Da Cookies in Ihrem Fall über Sitzungen hinweg bestehen bleiben, müssen Sie sie deaktivieren, sobald Sie alles getan haben, was Sie damit tun müssen. Sie möchten nicht, dass der Benutzer einen Tag später zurückkommt und immer noch clickedauf true gesetzt ist.

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

(Eine Nicht-jQuery-Methode zum Setzen / Lesen von Cookies finden Sie hier )

Ich persönlich würde ein Cookie nicht für etwas Einfaches wie das Erinnern an einen angeklickten Status verwenden, aber wenn die Abfragezeichenfolge keine Option ist und Sie wirklich alte Browser unterstützen müssen, die sessionStorage nicht unterstützen, funktioniert dies. Sie sollten dies zuerst mit einer Überprüfung auf sessionStorage implementieren und nur dann die Cookie-Methode verwenden, wenn dies fehlschlägt.


Fenstername

Obwohl dies für mich wie ein Hack erscheint, der wahrscheinlich vor localStorage / sessionStorage entstanden ist, können Sie Informationen in der window.nameEigenschaft speichern :

window.name = "my value"

Es können nur Zeichenfolgen gespeichert werden. Wenn Sie also ein Objekt speichern möchten, müssen Sie es wie im obigen localStorageBeispiel stringifizieren :

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

Der Hauptunterschied besteht darin, dass diese Informationen nicht nur über Seitenaktualisierungen, sondern auch über verschiedene Domänen hinweg gespeichert werden. Es ist jedoch auf die aktuelle Registerkarte beschränkt, in der Sie sich befinden.

Dies bedeutet, dass Sie einige Informationen auf Ihrer Seite speichern können. Solange der Benutzer auf dieser Registerkarte bleibt, können Sie auf dieselben Informationen zugreifen, selbst wenn er zu einer anderen Website und zurück navigiert. Im Allgemeinen würde ich davon abraten, dies zu verwenden, es sei denn, Sie müssen domänenübergreifende Informationen während einer einzelnen Browsersitzung speichern.

Stephan Müller
quelle
9
Ugh, erst nach dem Schreiben habe ich Ihre Kopfgeldbeschreibung gelesen, in der "keine Cookies oder lokaler Speicher" stand. Ich werde diesen Kommentar für andere, die ihn möglicherweise benötigen, intakt halten, aber Sie müssen nur die Abfragezeichenfolge verwenden, denke ich.
Stephan Müller
1
Grundsätzlich verwende ich localStorage in vielen Fällen bereits für meine Webanwendung und möchte vermeiden, zu viele localStorage-Variablen zu verwenden. Ich mag jedoch die Idee, das localStorage-Element zu entfernen, sobald ich damit fertig bin. Daran habe ich bei der Verwendung meiner localStorage-Variablen nicht gedacht.
Neophile
3
Im Falle einer Post-Anfrage können Sie das Aktionsattribut $ ("# formid"). Attr ("Aktion", URL + "& clicked = 1") ändern und auch GET oder POST von $ ("# formid") erkennen. Attr ( "Methode"), aber es kann nicht lösen, wie man das Nachladeproblem erkennt
Tero Tolonen
2
@TheNewbie Es ist schon eine Weile her, seit ich diese Antwort geschrieben habe, aber ich habe gerade eine neue Option hinzugefügt ( window.name). Es kann genau das tun, was Sie brauchen, ohne Cookies / localStorage zu verwenden.
Stephan Müller
1
Ich wollte hinzufügen, dass lokaler Speicher und Sitzungsspeicher auch in neueren Browsern nicht absolut zuverlässig sind. Normalerweise gibt es einen Fallback zu window.name.
JavaScript
5

Versuchen Sie es mit $.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>

guest271314
quelle
1

Verwenden localeStorageoder sessionStoragescheint die beste Wahl zu sein.

Anstatt die clickedVariable im Globle-Bereich zu speichern, speichern Sie sie folgendermaßen:

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
quelle
Ich beabsichtige, localstorage oder sessionStorage vorzugsweise nicht zu verwenden.
Neophile
-5

Sie könnten dies versuchen:

 $("input[type='submit'][value='Search']").click(function(){
     form.act.value='detailSearch'; 
     clicked = true;  
     return true;
});
renakre
quelle
Wenn die Seite neu geladen wird, wird der angeklickte Wert weiterhin als falsch angezeigt.
Neophile
1
@TheNewbie Glaubst du, du kannst eine Abfragezeichenfolge übergeben? Mit der Seitenaktualisierung funktioniert der aktuelle Ansatz nicht.
Renakre