Персистентные переменные между загрузками страниц

Я пытаюсь зафиксировать нажатие кнопки отправки моей формы и, если форма отправлена, страница обновляется, и я показываю несколько скрытых полей. Я хотел бы зафиксировать, была ли форма представлена ​​до или нет, и если она была отправлена ​​при перезагрузке, я хотел бы отобразить скрытые поля. Я пытался использовать глобальную переменную для достижения этой цели, однако мне не удалось заставить ее работать должным образом.

Вот что я пробовал:

  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

Поскольку 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. Поэтому, когда страница загружается снова с помощью этой строки запроса, вы можете проверить, была ли нажата кнопка.

Чтобы прочитать эти данные, вы можете использовать следующие script при загрузке страницы:

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, это может быть проблематично.

Кроме того, для более крупных наборов данных это менее оптимально. Передача строки - это не большая проблема, но для массивов и объектов данных вы, вероятно, должны использовать веб-хранилище или файлы cookie. Хотя данные немного отличаются друг от друга в браузерах, практический предел длины URI составляет 2000 символов


Веб-хранилище

С введением HTML5 мы также получили веб-хранилище, которое позволяет сохранять информацию в браузере на разных страницах. Существует localStorage, который может сохранять данные в течение более длительного периода (пока пользователь не очистит его вручную) и sessionStorage, который сохраняет данные только во время текущего сеанса просмотра. Последнее полезно для вас здесь, потому что вы не хотите, чтобы "clicked" был установлен в true, когда пользователь возвращается позже.

Здесь я устанавливаю хранилище на событие нажатия кнопки, но вы также можете привязать его к форме submit или что-то еще.

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

Затем, когда вы загружаете страницу, вы можете проверить, установлено ли это с помощью этого:

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

Несмотря на то, что это значение сохраняется только во время сеанса просмотра, возможно, вы захотите его reset ранее. Для этого используйте:

sessionStorage.removeItem('clicked');

Если вы хотите сохранить объект или массив JS, вы должны преобразовать его в строку. Согласно спецификации, должно быть возможно сохранить другие типы данных, но это пока неправильно реализовано в браузерах.

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

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

Поддержка браузера довольно хорошая, поэтому вы должны быть в безопасности, чтобы использовать это, если вам не нужно поддерживать действительно старые/неясные браузеры. Веб-хранилище - это будущее.


Cookies

Альтернативой веб-хранилищу является сохранение данных в файле 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');

Поскольку файлы cookie сохраняются на всех сеансах в вашем случае, вам нужно будет их отключить, как только вы сделаете все, что вам нужно сделать. Вы не хотите, чтобы пользователь возвращался через день и все еще имел clicked значение true.

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

(здесь не поддерживается jQuery для установки/чтения файлов cookie здесь)

Я лично не использовал бы cookie для чего-то простого, поскольку помню состояние щелчка, но если строка запроса не является опцией, и вам нужно поддерживать действительно старые браузеры, которые не поддерживают sessionStorage, это будет работать. Вы должны реализовать это, сначала проверив sessionStorage, и только если это не поможет, используйте метод cookie.


window.name

Хотя это кажется взломом для меня, который, вероятно, произошел из-за localStorage/sessionStorage, вы могли хранить информацию в свойстве window.name:

window.name = "my value"

Он может хранить только строки, поэтому, если вы хотите сохранить объект, вам придется его спрятать так же, как приведенный выше пример localStorage:

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

Основное отличие заключается в том, что эта информация сохраняется не только для обновления страниц, но и для разных доменов. Однако он ограничен текущей вкладкой, в которой вы находитесь.

Это означает, что вы можете сохранить некоторую информацию на своей странице, и пока пользователь остается на этой вкладке, вы можете получить доступ к этой же информации, даже если он перешел на другой веб-сайт и обратно. В общем, я бы посоветовал использовать это, если вам не нужно фактически хранить кросс-доменную информацию в течение одного сеанса просмотра.

Ответ 2

Попробуйте использовать $.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>

Ответ 3

Использование localeStorage или sessionStorage кажется лучшим выбором.

Интеграция сохранения переменной 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
    }

});

Ответ 4

Вы можете попробовать следующее:

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