Variabel tetap di antara pemuatan halaman

97

Saya mencoba menangkap penekanan tombol kirim formulir saya dan jika formulir dikirim, halaman disegarkan dan saya menampilkan beberapa bidang tersembunyi. Saya ingin menangkap apakah formulir telah dikirimkan sebelumnya atau tidak dan jika dikirimkan saat dimuat ulang, saya ingin menampilkan bidang tersembunyi. Saya mencoba menggunakan variabel global untuk mencapai ini, namun saya tidak dapat membuatnya berfungsi dengan baik.

Inilah yang saya coba:

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

Ada saran tentang apa yang salah dengan kode ini?

Neophile
sumber
1
Saya tidak berpikir ini bisa dilakukan tanpa semacam penyimpanan. Variabel JS Anda semuanya akan bersih. Seluruh ruang lingkup Anda akan didaur ulang.
Dave Alperovich
Mengapa Anda tidak menempatkan sebagian besar halaman Anda menjadi "sebagian" dan menyegarkannya?
Dave Alperovich
Apa yang parsial? Maaf saya tidak menyadarinya.
Neophile
Sudahkah Anda mempertimbangkan untuk mengirimkan formulir melalui ajax dan menunjukkan bidang setelah penyerahan?
dannyshaw
1
Dapatkah Anda menjelaskan mengapa Anda membutuhkan halaman untuk disegarkan? Jika kami dapat menghindarinya, Anda mungkin dapat melakukan apa yang Anda inginkan jika Anda hanya preventDefaultpada submitacara tersebut (bukan yang clickAnda gunakan.)
Peleg

Jawaban:

207

Karena HTTP tidak memiliki kewarganegaraan, setiap kali Anda memuat halaman, ia akan menggunakan nilai awal dari apa pun yang Anda tetapkan di JavaScript. Anda tidak dapat menyetel variabel global di JS dan cukup membuat nilai itu tetap ada setelah memuat halaman lagi.

Ada beberapa cara untuk menyimpan nilai di tempat lain sehingga Anda dapat menginisialisasinya saat dimuat menggunakan JavaScript


String kueri

Saat mengirimkan formulir menggunakan GETmetode ini, url diperbarui dengan string kueri ( ?parameter=value&something=42). Anda dapat memanfaatkan ini dengan mengatur kolom input di formulir ke nilai tertentu. Ini akan menjadi contoh paling sederhana:

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

Pada pemuatan awal halaman, tidak ada string kueri yang ditetapkan. Saat Anda mengirimkan formulir ini, filenamevalue kombinasi dan masukan akan diteruskan dalam string kueri sebagai clicked=true. Jadi ketika halaman memuat lagi dengan string kueri itu Anda dapat memeriksa apakah tombol itu diklik.

Untuk membaca data ini, Anda dapat menggunakan script berikut pada pemuatan halaman:

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

( Sumber )

Kemampuan untuk menggunakan ini tergantung pada bagaimana formulir Anda saat ini bekerja, jika Anda sudah menggunakan POST maka ini bisa menjadi masalah.

Selain itu, untuk kumpulan data yang lebih besar, ini kurang dari optimal. Meneruskan string bukanlah masalah besar, tetapi untuk array dan objek data, Anda mungkin harus menggunakan Penyimpanan Web atau cookie. Meskipun detailnya sedikit berbeda di semua browser, batas praktis untuk panjang URI adalah sekitar 2000 karakter


Penyimpanan Web

Dengan diperkenalkannya HTML5, kami juga mendapatkan Penyimpanan Web, yang memungkinkan Anda menyimpan informasi di browser saat memuat halaman. AdalocalStorage yang dapat menyimpan data untuk waktu yang lebih lama (selama pengguna tidak menghapusnya secara manual) dan sessionStorageyang hanya menyimpan data selama sesi penjelajahan Anda saat ini. Yang terakhir berguna untuk Anda di sini, karena Anda tidak ingin "diklik" disetel ke true saat pengguna kembali lagi nanti.

Di sini saya mengatur penyimpanan pada acara klik tombol, tetapi Anda juga bisa mengikatnya ke formulir kirim atau apa pun.

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

Kemudian saat Anda memuat halaman, Anda dapat memeriksa apakah sudah diatur menggunakan ini:

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

Meskipun nilai ini hanya disimpan selama sesi penjelajahan ini, ada kemungkinan Anda ingin mengatur ulang lebih awal. Untuk melakukannya, gunakan:

sessionStorage.removeItem('clicked');

Jika Anda ingin menyimpan objek atau larik JS, Anda harus mengubahnya menjadi string. Menurut spesifikasi, seharusnya dimungkinkan untuk menyimpan tipe data lain, tetapi ini belum diterapkan dengan benar di seluruh browser.

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

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

Dukungan browser cukup bagus sehingga Anda harus aman menggunakan ini kecuali Anda perlu mendukung browser yang sangat lama / tidak jelas. Penyimpanan Web adalah masa depan.


Kue

Alternatif untuk Penyimpanan Web adalah menyimpan data dalam cookie. Cookies terutama dibuat untuk membaca data sisi server, tetapi juga dapat digunakan untuk data sisi klien murni.

Anda sudah menggunakan jQuery, yang membuat pengaturan cookie menjadi cukup mudah. Sekali lagi, saya menggunakan clickacara di sini tetapi bisa digunakan di mana saja.

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

Kemudian pada pemuatan halaman Anda dapat membaca cookie seperti ini:

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

Karena cookie bertahan di seluruh sesi dalam kasus Anda, Anda harus membatalkannya segera setelah Anda melakukan apa pun yang perlu Anda lakukan dengannya. Anda tidak ingin pengguna kembali satu hari kemudian dan tetap clickedmenyetel ke true.

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

(cara non-jQuery untuk mengatur / membaca cookie dapat ditemukan di sini )

Saya pribadi tidak akan menggunakan cookie untuk sesuatu yang sederhana seperti mengingat status yang diklik, tetapi jika string kueri bukan opsi dan Anda perlu mendukung browser yang benar-benar lama yang tidak mendukung sessionStorage, ini akan berfungsi. Anda harus mengimplementasikannya dengan memeriksa sessionStorage terlebih dahulu, dan hanya jika gagal menggunakan metode cookie.


window.name

Meskipun bagi saya ini tampak seperti peretasan yang mungkin berasal dari sebelum localStorage / sessionStorage, Anda dapat menyimpan informasi di window.nameproperti:

window.name = "my value"

Itu hanya dapat menyimpan string, jadi jika Anda ingin menyimpan objek, Anda harus merangkai seperti localStoragecontoh di atas :

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

Perbedaan utamanya adalah bahwa informasi ini disimpan tidak hanya di penyegaran halaman tetapi juga domain yang berbeda. Namun, itu terbatas pada tab tempat Anda berada saat ini.

Ini berarti Anda dapat menyimpan beberapa informasi di halaman Anda dan selama pengguna tetap berada di tab itu, Anda dapat mengakses informasi yang sama bahkan jika dia menjelajahi situs web lain dan sebaliknya. Secara umum, saya akan menyarankan agar tidak menggunakan ini kecuali Anda benar-benar perlu menyimpan informasi lintas domain selama satu sesi penjelajahan.

Stephan Muller
sumber
9
Ugh, baru setelah menulis saya membaca deskripsi hadiah Anda yang mengatakan "tidak ada cookie atau penyimpanan lokal". Saya akan menjaga komentar ini tetap utuh untuk orang lain yang mungkin membutuhkannya, tetapi Anda hanya perlu menggunakan string kueri yang saya kira.
Stephan Muller
1
Pada dasarnya saya sudah menggunakan localStorage dalam banyak kasus untuk aplikasi web saya dan saya ingin menghindari penggunaan terlalu banyak variabel localStorage. Namun saya menyukai ide untuk menghapus item localStorage setelah saya selesai dengan itu. Itu adalah sesuatu yang tidak terpikirkan oleh saya saat menggunakan variabel localStorage saya.
Neophile
3
Dalam kasus permintaan posting, Anda dapat memodifikasi action -attribute $ ("# formid"). Attr ("action", url + "& clicked = 1") dan juga mendeteksi GET atau POST dari $ ("# formid"). Attr ( "metode") tetapi mungkin tidak menyelesaikan cara mendeteksi masalah muat ulang
Tero Tolonen
2
@TheNewbie sudah lama sejak saya menulis jawaban ini, tetapi saya baru saja menambahkan opsi baru ( window.name). Itu mungkin hanya melakukan apa yang Anda butuhkan tanpa menggunakan cookie / localStorage.
Stephan Muller
1
Saya ingin menambahkan bahwa penyimpanan lokal dan sesi tidak sepenuhnya dapat diandalkan pada browser yang lebih baru juga. Biasanya ada fallback ke window.name.
JavaScript
5

Coba manfaatkan $.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>

tamu271314
sumber
1

Menggunakan localeStorageatau sessionStoragetampaknya menjadi taruhan terbaik.

Daripada menyimpan clickedvariabel dalam lingkup globle, simpan dengan cara ini:

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
sumber
Saya bermaksud untuk tidak menggunakan penyimpanan lokal atau penyimpanan sesi lebih disukai.
Neophile
-5

Anda bisa mencoba ini:

 $("input[type='submit'][value='Search']").click(function(){
     form.act.value='detailSearch'; 
     clicked = true;  
     return true;
});
renakre
sumber
Saat halaman dimuat ulang, tetap mendapatkan nilai yang diklik sebagai false.
Neophile
1
@TheNewbie menurut Anda apakah Anda dapat mengirimkan string kueri? dengan penyegaran halaman, pendekatan saat ini tidak akan berfungsi.
renakre