【发布时间】:2013-01-16 06:01:12
【问题描述】:
我的场景:我有一个 9 页长的应用程序,总共有大约 125 个不同类型和大小的输入(仅输入、文本区域、单选和选择)。我想使用本地存储来保存表单值。用户可以在页面之间移动(例如,在提交申请之前进行审查),所以我不想在他们提交申请之前清除本地存储,如果他们从一个页面更改为另一个页面,表单应该从本地存储重新加载它的值.他们提交表单后,我将清除本地存储,但在此之前,应保留本地存储。
我发现这个很棒的 jquery plugin 和一个 demo page 似乎几乎可以满足我的要求 - 嗯,有两个例外:
1) 该插件会提示用户是否要恢复他们以前输入的我不想拥有的信息(我宁愿让数据就在那里)。我在表格底部的导航按钮只是“上一个”和“继续”(在第一页上,它只是“继续”,在最后一页上它们将是“上一个”和“提交申请”)。
2) 即使没有要加载的数据,插件也会提示用户(如果我可以让它加载数据,如果有的话,这将是一个非问题,如果没有则跳过它)。例如,第一次访问页面会提示用户恢复之前输入的数据。
这里是演示页面中使用的jquery.remember-state.js 的链接。
================================================ ========
我采用了上面的演示并将 jquery.remember-state.js 调整为 try 并让它做我需要的,但它不能正常工作。
这是我的 (jsFiddle)。
注意 1: jsFiddle 仅用于显示我的代码,不一定是 jsFiddle 环境中的工作示例。如果您将代码复制到本地环境,您应该能够访问 console.log 以查看是否/什么保存到 localStorage。
注意 2: S.O.想要格式化的代码内联,所以我会看看我能做些什么来使它正确格式化。
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<title>LocalStorage and Unload State Save</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="../jQueryPlugins/RememberState/form.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- use the modified jquery.remember-state.js code in the JavaScript panel instead
the script tag below is the original js file
<script src="http://shaneriley.com/jquery/remember_state/jquery.remember-state.js"></script>-->
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
(function($) {
/* jQuery form remember state plugin
Name: rememberState
Version: 1.3
Description: When called on a form element, localStorage is used to
remember the values that have been input up to the point of either
saving or unloading. (closing window, navigating away, etc.) If
localStorage isn't available, nothing is bound or stored.
The plugin looks for an element with a class of remember_state to show
a note indicating there is stored data that can be repopulated by clicking
on the anchor within the remember_state container. If the element doesn't
exist, it is created and prepended to the form.
Usage: $("form").rememberState("my_object_name");
Notes: To trigger the deletion of a form's localStorage object from
outside the plugin, trigger the reset_state event on the form element
by using $("form").trigger("reset_state");
*/
if (!window.localStorage || !window.JSON) {
if (console && console.log) {
!window.localStorage && console.log("ERROR: you browser does not support" +
" localStorage (use this polyfill https://gist.github.com/350433)");
!window.JSON&& console.log("ERROR: you browser does not support" +
" JSON (use this polyfill http://bestiejs.github.com/json3/)");
}
return $.fn.rememberState = function() { return this; };
}
var remember_state = {
name: "rememberState",
clearOnSubmit: false, //default was true;
// ****************************
/*noticeDialog: (function() {
return $("<p />", {"class": "remember_state"})
.html('Do you want to <a href="#">restore your previously entered info</a>?');
})(),*/
// ****************************
ignore: null,
noticeSelector: ".remember_state",
use_ids: false,
objName: false,
clickNotice: function(e) {
var data = JSON.parse(localStorage.getItem(e.data.instance.objName)),
$f = $(this).closest("form"),
$e;
for (var i in data) {
$e = $f.find("[name=\"" + data[i].name + "\"]");
if ($e.is(":radio, :checkbox")) {
$e.filter("[value=" + data[i].value + "]").prop("checked", true);
}
else if ($e.is("select")) {
$e.find("[value=" + data[i].value + "]").prop("selected", true);
}
else {
$e.val(data[i].value);
}
$e.change();
}
e.data.instance.noticeDialog.remove();
e.preventDefault();
},
chooseStorageProp: function() {
if (this.$el.length > 1) {
if (console && console.warn) {
console.warn("WARNING: Cannot process more than one form with the same" +
" object. Attempting to use form IDs instead.");
}
this.objName = this.$el.attr("id");
}
},
errorNoID: function() {
if (console && console.log) {
console.log("ERROR: No form ID or object name. Add an ID or pass" +
" in an object name");
}
},
saveState: function(e) {
var instance = e.data.instance;
var values = instance.$el.serializeArray();
// jQuery doesn't currently support datetime-local inputs despite a
// comment by dmethvin stating the contrary:
// http://bugs.jquery.com/ticket/5667
// Manually storing input type until jQuery is patched
instance.$el.find("input[type='datetime-local']").each(function() {
var $i = $(this);
values.push({ name: $i.attr("name"), value: $i.val() });
});
values = instance.removeIgnored(values);
values.length && internals.setObject(instance.objName, values);
},
save: function() {
var instance = this;
if (!this.saveState) {
instance = this.data(remember_state.name);
}
instance.saveState({ data: { instance: instance } });
},
removeIgnored: function(values) {
if (!this.ignore) { return values; }
$.each(this.ignore, function(i, name) {
$.each(values, function(j, input) {
if (name === input.name) { delete values[j]; }
});
});
return values;
},
init: function() {
var instance = this;
// ****************************
/* if (instance.noticeDialog.length && instance.noticeDialog.jquery) {
instance.noticeDialog.find("a").bind("click." + instance.name, {
instance: instance
}, instance.clickNotice);
}*/
// ****************************
instance.chooseStorageProp();
if (!instance.objName) {
instance.errorNoID();
return;
}
if (localStorage[instance.objName]) {
// ****************************
/*if (instance.noticeDialog.length && typeof instance.noticeDialog === "object") {
instance.noticeDialog.prependTo(instance.$el);
}
else {
instance.$el.find(instance.noticeSelector).show();
}*/
// ****************************
}
if (instance.clearOnSubmit) {
instance.$el.bind("submit." + instance.name, function() {
instance.$el.trigger("reset_state");
$(window).unbind("unload." + instance.name);
});
}
instance.$el.bind("reset_state." + instance.name, function() {
localStorage.removeItem(instance.objName);
});
// ****************************
/*$(window).bind("unload." + instance.name, { instance: instance }, instance.saveState);
instance.$el.find(":reset").bind("click.remember_state", function() {
$(this).closest("form").trigger("reset_state");
});*/
}
};
var internals = {
setObject: function(key, value) { localStorage[key] = JSON.stringify(value); },
getObject: function(key) { return JSON.parse(localStorage[key]); },
createPlugin: function(plugin) {
$.fn[plugin.name] = function(opts) {
var $els = this,
method = $.isPlainObject(opts) || !opts ? "" : opts;
if (method && plugin[method]) {
plugin[method].apply($els, Array.prototype.slice.call(arguments, 1));
}
else if (!method) {
$els.each(function(i) {
var plugin_instance = $.extend(true, {
$el: $els.eq(i)
}, plugin, opts);
$els.eq(i).data(plugin.name, plugin_instance);
plugin_instance.init();
});
}
else {
$.error('Method ' + method + ' does not exist on jQuery.' + plugin.name);
}
return $els;
};
}
};
internals.createPlugin(remember_state);
})(jQuery);
});//]]>
</script>
<script>
var thisPage = 'page1'; //defines the variable to use for local storage
$(function() {
$("form")
.rememberState({objName: thisPage})
.submit(function() {localStorage.setItem(thisPage, $(this).serializeArray());
return true;
});
});
</script>
</head>
<body>
<form method="post" action="page2.cfm">
<fieldset>
<dl>
<dt><label for="first_name">First Name</label></dt>
<dd><input type="text" name="first_name" id="first_name" /></dd>
<dt><label for="last_name">Last Name</label></dt>
<dd><input type="text" name="last_name" id="last_name" /></dd>
</dl>
</fieldset>
<fieldset class="actions">
<input type="submit" value="Continue" />
</fieldset>
</form>
</body>
</html>
【问题讨论】:
-
我还应该补充一点,我没有与这个插件结婚,所以我对其他插件持开放态度。虽然数据库可用,但客户宁愿不使用数据库,以免遭到黑客攻击。表格将在完成后通过电子邮件发送。这是一个小型非营利组织。
-
为什么需要插件?为什么不直接使用 localStorage API?
-
根据我的阅读,您只能在本地将数据保存为 field1=value1、filed2=value2 等。在我找到的一些插件中,您可以分配类似 page1=[ field1=value1, filed2=value2, etc], page2=[field1=value1, filed2=value2, etc.] 这将允许更有条理的localStorage。我的插件不是必需的,我只是觉得它可能更容易。
-
使用 JSON 序列化,您可以存储任何普通对象。这很容易,所有问题都会得到解决。 BTW,使用localStorage不正确,这里必须使用sessionStorage。
-
@KyawTun - 你为什么说 sessionStorage 是正确的?我想为用户提供稍后回来填写应用程序的其余部分的选项,并且我对使用存储的了解有限,因此本地存储会更加持久。我错了吗?
标签: javascript jquery local-storage