ページの読み込み間で変数を保持する


95

フォームの送信ボタンの押下をキャプチャしようとしています。フォームが送信されると、ページが更新され、いくつかの非表示フィールドが表示されます。フォームが以前に送信されたかどうかをキャプチャし、再読み込み時に送信された場合、非表示のフィールドを再表示したいと思います。これを達成するためにグローバル変数を使用しようとしましたが、適切に機能させることができませんでした。

これが私が試したものです:

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

このコードの何が問題になっているのですか?


1
これはなんらかのストレージなしでは実現できないと思います。JS変数はすべてクリーンアップされます。スコープ全体がリサイクルされます。
Dave Alperovich

ほとんどのページを「部分的」にして、それを更新してみませんか?
Dave Alperovich、

パーシャルとは何ですか?申し訳ありませんが、そのことは認識していません。
Neophile

ajax経由でフォームを送信し、送信後にフィールドを表示することを検討しましたか?
dannyshaw

1
ページを更新する必要がある理由を詳しく説明できますか?我々はそれを避けることができれば、あなたがもしあなたがちょうどやりたいことができるかもしれないpreventDefault上のsubmitイベント(の代わりにclick使用している。)
ペレグ

回答:


202

HTTPはステートレスであるため、ページをロードするたびに、JavaScriptで設定したものの初期値が使用されます。JSでグローバル変数を設定して、ページを再度ロードした後、その値をそのままにしておくことはできません。

JavaScriptを使用してロード時に値を初期化できるように、値を別の場所に格納する方法はいくつかあります


クエリ文字列

GETメソッドを使用してフォームを送信すると、URLはクエリ文字列(?parameter=value&something=42)で更新されます。フォームの入力フィールドを特定の値に設定することにより、これを利用できます。これが最も簡単な例です。

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

ページの初期読み込み時に、クエリ文字列は設定されません。このフォームを送信すると、nameおよびvalueの入力の組み合わせがとしてクエリ文字列に渡されますclicked=true。したがって、そのクエリ文字列でページが再度読み込まれると、ボタンがクリックされたかどうかを確認できます。

このデータを読み取るには、ページの読み込み時に次のスクリプトを使用できます。

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

出典

これを使用できるかどうかは、フォームが現在どのように機能しているかによって異なります。すでにPOSTを使用している場合は、問題が発生する可能性があります。

さらに、より大きなデータセットの場合、これは最適ではありません。文字列を渡すことは大したことではありませんが、データの配列やオブジェクトの場合は、おそらくWeb StorageまたはCookieを使用する必要があります。詳細はブラウザによって多少異なりますが、URIの長さの実際的な制限は約2000文字です


Webストレージ

HTML5の導入により、Web Storageも使用できるようになりました。これにより、ページをロードしてもブラウザに情報を保存できます。ありlocalStorage長い期間のデータを保存することができた(ユーザー限り、手動でそれをクリアしない)とsessionStorage、現在のブラウジングセッション中にのみデータを保存します。後者は、ユーザーが後で戻ってきたときに「クリック」をtrueに設定したままにしたくないので、ここでは便利です。

ここでは、ボタンクリックイベントにストレージを設定しますが、フォーム送信または他の何かにバインドすることもできます。

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

次に、ページをロードするときに、次のように設定されているかどうかを確認できます。

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

この値はこのブラウジングセッション中にのみ保存されますが、以前にリセットすることもできます。これを行うには、以下を使用します。

sessionStorage.removeItem('clicked');

JSオブジェクトまたは配列を保存する場合は、それを文字列に変換する必要があります。仕様によると、他のデータ型を保存することは可能であるはずですが、これはまだブラウザー間で正しく実装されていません。

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

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

ブラウザのサポートは非常に優れているので、本当に古い/あいまいなブラウザをサポートする必要がない限り、これを使用しても安全です。Webストレージは未来です。


クッキー

Web Storageに代わる方法は、データをCookieに保存することです。Cookieは主にサーバー側のデータを読み取るために作成されますが、純粋にクライアント側のデータにも使用できます。

すでにjQueryを使用しているため、Cookieの設定は非常に簡単です。繰り返しclickますが、ここではイベントを使用しますが、どこでも使用できます。

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

次に、ページの読み込み時に、次のようにCookieを読み取ることができます。

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

あなたのケースではクッキーはセッション間で持続するので、あなたがそれを行うために必要なことをすべて行ったらすぐにそれらを設定解除する必要があります。ユーザーが1日後に戻ってきて、まだclickedtrueに設定されていることを望まないでしょう。

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

(Cookieを設定/読み取るためのjQuery以外の方法はここにあります

個人的には、クリックされた状態を記憶するような単純なものにはCookieを使用しませんが、クエリ文字列がオプションではなく、sessionStorageをサポートしない本当に古いブラウザーをサポートする必要がある場合、これは機能します。最初にsessionStorageをチェックして実装し、それが失敗した場合にのみcookieメソッドを使用してください。


window.name

これはおそらくlocalStorage / sessionStorageの前から始まったハックのようですが、window.nameプロパティに情報を格納できます。

window.name = "my value"

これは文字列のみを保存できるため、オブジェクトを保存する場合は、上記のlocalStorage例のように文字列化する必要があります。

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

主な違いは、この情報はページの更新だけでなく、さまざまなドメインでも保持されることです。ただし、現在のタブに制限されています。

つまり、ページにいくつかの情報を保存でき、ユーザーがそのタブに留まっている限り、ユーザーが別のWebサイトにアクセスして戻った場合でも、同じ情報にアクセスできます。一般的に、1つのブラウジングセッション中に実際にクロスドメイン情報を保存する必要がない限り、これを使用しないことをお勧めします。


9
ええと、私は「クッキーもローカルストレージもない」と述べたあなたの賞金の説明を書いて初めて読みました。このコメントは、必要になる可能性のある他の人のためにそのまま残しておきますが、私が推測するクエリ文字列を使用するだけで済みます。
ステファンミュラー

1
基本的に、私は自分のWebアプリケーションの多くの場合にすでにlocalStorageを使用しており、あまりにも多くのlocalStorage変数を使用しないようにしたいと思います。しかし、私はそれが終わったらlocalStorageアイテムを削除するという考えが好きです。これは、localStorage変数を使用するときに考えなかったものです。
ネオフィル

3
投稿リクエストの場合、アクション-属性$( "#formid")。attr( "action"、url + "&clicked = 1")を変更し、$( "#formid")。attr(からのGETまたはPOSTを検出することもできます。 「方法」)が、リロードの問題を検出する方法を解決しない可能性があります
Tero Tolonen '11年

2
@TheNewbie私がこの回答を書いてから久しぶりですが、新しいオプション(window.name)を追加しました。cookie / localStorageを使用せずに、必要なことを正確に実行できます。
ステファンミュラー2015年

1
ローカルストレージとセッションストレージは、新しいブラウザでも完全に信頼できるわけではないことを付け加えておきます。通常、window.nameへのフォールバックがあります。
JavaScriptを使用して

5

利用してみてください$.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

を使用するlocaleStoragesessionStorage、最善の策のようです。

clicked変数をglobleスコープに保存する代わりに、次のように保存します。

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
    }

});

私はできればlocalstorageやsessionStorageを使わないつもりです。
ネオフィル

-5

あなたはこれを試すことができます:

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

ページがリロードしても、クリックされた値はfalseのままです。
ネオフィル、2015年

1
@TheNewbieあなたはクエリ文字列を渡すことができると思いますか?ページの更新では、現在のアプローチは機能しません。
レナクル、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.