【问题标题】:Back Button Handle A Dynamic Form后退按钮处理动态表单
【发布时间】:2010-12-16 00:49:37
【问题描述】:

我有一个包含文本字段数组的表单。用户(通过 javascript)可以向表单添加任意数量的文本字段。提交表单并按下后退按钮后,表单仅显示第一次呈现时原始表单上的字段(任何添加的文本字段都将丢失)。允许后退按钮以用户提交表单时的状态呈现表单的最佳方法是什么?欢迎任何想法,我尝试过的一些事情是:

  • 将表单数据放入 cookie(此 不适合一对夫妇 原因,但对我来说是最大的杀手 是 cookie 被限制在 4K 大小)
  • 将表单数据放入会话中
  • 通过 AJAX 提交表单,然后管理历史记录

感谢您的帮助。我已经在我的网站http://fishtale.org/formtest/f1.php 上发布了一份测试表。这里还有一个简单的形式展示了我提到的行为:

<form action="f2.php" method="post">
<input type="text" name="text[]" id="text1"/>
<input type="submit" name="saveaction" value="submit form" />
</form>

<a href="f2.php" id="add_element">Add Form Element</a>

<script type="text/javascript" 
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js" ></script>

<script type="text/javascript" >
    $('#add_element').click(function (event) {
        event.preventDefault();
        $('#text1').after('<input type="text" name="text[]" />');
    });
</script>

这类似于我前段时间发布的一个问题Best Way For Back Button To Leave Form Data,但是,此表单的元素是由用户修改的。

【问题讨论】:

  • 嗨,Brian,您反对使用临时 cookie 来存储值吗?您的用户通常会添加多少个字段?如果这听起来像是一个很好的解决方案,我会提供代码。
  • 嘿,Doug,用户正在创建一个时间卡,因此他们可以添加相当多的元素,大约为 100。我不确定我是否反对临时 cookie,如果他们工作我都支持他们。我认为如果总 cookie 大小超过 4K 最大值,它们可能会导致其他 cookie 出现问题。谢谢。

标签: javascript html forms back-button


【解决方案1】:

如何创建一个&lt;input type="hidden"&gt;(没有name 或在表单之外,因此不会提交),在其中存储要添加的额外字段的编码列表及其值?虽然浏览器不会记住“返回”上新添加的字段,但它记住从一开始就在表单中的隐藏字段的值。

这是一个示例,它在文档卸载时保存额外的字段并在准备好时检索它们:

<input type="hidden" id="remembertexts" />

<form action="http://www.google.com/" method="get">
    <div id="texts">
        <input type="text" name="text[]" value="" />
    </div>
    <div>
        <input type="submit" />
        <input type="button" id="addtext" value="+" />
    </div>
</form>

<script type="text/javascript">

    // Add new field on button press
    //
    $('#addtext').click(function() {
        addInput('');
    });

    function addInput(text) {
        $('#texts input').eq(0).clone().val(text).appendTo('#texts');
    };

    // Store dynamic values in hidden field on leaving
    //
    $(window).bind('beforeunload', function() {
        var vals= [];
        $('#texts input').each(function() {
            vals.push(encodeURIComponent(this.value));
        });
        $('#remembertexts').val(vals.join(';'));
    });

    // Retrieve dynamic values on returning to page
    //
    $(function() {
        var extratexts= $('#remembertexts').val().split(';').slice(1);
        $.each(extratexts, function() {
            addInput(decodeURIComponent(this));
        });
    });
</script>

注意事项:

  • 如果您只需要在提交时记住值,则可以使用 form.onsubmit 而不是 window.onbeforeunloadonunload 不起作用,因为某些浏览器在该事件发生之前已经存储了旧的表单值。

  • 在 Firefox 中,隐藏输入的位置很重要。出于某种原因,如果您将其放在动态添加的字段下方,Firefox 会混淆它是哪个输入并且无法记住该值。

  • 此示例在 Opera 中不起作用。它可以在 Opera 中工作,但它很痛苦。 Opera 对加载和卸载事件的调用不一致,因此您必须使用 onsubmit 代替,或者在轮询间隔上设置隐藏字段等。更糟糕的是,当 Opera 记住以前的表单字段值时,它实际上直到 onload 触发后才填写它们!这已经导致了很多很多表单脚本问题。如果您需要 Opera 兼容性,您可以通过在 onload 中设置一个小超时以等待表单值输入来解决此问题。

【讨论】:

【解决方案2】:

我找不到为此预先编写的库,但我确信它之前已解决。如果我必须自己这样做,我会采取这种方法:

  1. 使用command pattern,以便通过添加控件来修改页面 UI 的每个方法也调用 AJAX 方法,以将调用的方法(文本 Javascript 表示)推送到存储在服务器会话中的队列中。

  2. body onLoad 完成后,使用 AJAX 方法在服务器会话中查询用户所在页面的命令队列。如果检索到一个,只需 eval 队列中的每个成员按照用户执行的顺序重建页面的 UI。

请记住,使用这种方法,您不仅记录了控件的添加,还记录了删除。您需要为用户输入控件设置单独的状态持有者,例如文本框(您可能还需要具有 AJAX 方法访问权限的服务器端会话)。

【讨论】:

  • 听起来很有趣,我会试一试。你提到“用户输入控件的独立状态持有者”你是什么意思?谢谢。
  • 如果按钮单击添加了一个文本框 ('text2'),您的方法将推送一个 'addTextBox("text2");' JavaScript 命令到您的 AJAX 服务。这一切都很好。问题是用户将在所述文本框中键入文本。您将需要这些文本框(或其他控件)将所述数据中继到服务器,因此当您重新创建 UI 时,您还需要重新创建用户输入到控件中的值。您也可以使用命令模式来解决这个问题,方法是将 JavaScript 函数推送到命令队列中来设置值。
  • 那里 必须 有一个图书馆可以做到这一点,不幸的是,谷歌搜索“记录和重放 Javascript”并没有让我明白这一点。
  • MS 为他们的 AJAX 和 ASP.NET 东西提供了一个称为“历史点”的东西,它利用查询字符串进行状态存储 (ug),但我没有看到用于执行此操作的通用库。
  • 这是一种有趣的替代方法,您可以将 URL 插入浏览器的历史记录:oracle.com/technology/pub/articles/dev2arch/2006/01/… 还可以查看第 3 页上的参考以获取更多想法。
【解决方案3】:

在优秀的浏览器中,您只需不破坏它就可以让它完美运行。

Firefox 1.5 对整个网页使用内存缓存,包括它们的 JavaScript 状态,用于单个浏览器会话。在访问的页面之间来回移动不需要页面加载,并且保留 JavaScript 状态。 source

OperaWebKit 也支持此功能。然而 DOM 缓存只有在你遵守规则的情况下才有可能:

  1. 不要使用onunloadonbeforeunload
  2. 不要使用Cache-control: no-storemust-revalidate
    在 PHP 中,您必须将 session.cache_limiterpatently_ridiculous(我认为他们拼写为 nocache)更改为 none

    session_cache_limiter('none');
    
  3. 很遗憾,HTTPS 也被淘汰了。

如果您不强制浏览器重新加载页面,它们不会。他们将保持 DOM 及其值不变,与 RFC 2616 suggests 完全相同。


然而,如果您正在寻找存储数据的地方,这里有一个非常聪明的 hack – window.name can store megabytes of data。它不发送到服务器,也不在窗口之间共享。

还有 Flash cookie 和 HTML 5 localStorage 在 IE8 和 Safari 4 中实现。

【讨论】:

  • 在我的示例中,当我在 FF3.5、Chrome 或 IE 8 中按下后退按钮时,由 javascript 动态添加的字段不会重新创建。我相信我的 http 标头设置正确。我也尝试使用 session_cache_limiter('none'),但没有改变。有什么我想念的吗?
  • jQuery 使用 onunload 堵住 IE 内存泄漏,onunload 中断缓存:groups.google.com/group/jquery-dev/browse_thread/thread/…
  • 另一个关于 jQuery 打破这个的帖子:friendfeed.com/paul/2b7ddce5/…
【解决方案4】:

第 2 步:处理表单的脚本将输入的值放入一个数组中,并将该数组存储到一个会话变量(或 text/db/任何您认为合适的变量)中。

第 1 步:如果找到该会话变量(并且它还清除会话变量),则输出表单的脚本会添加一个 javascript(反过来填充表单)。

【讨论】:

    【解决方案5】:

    您可以在网页顶部制作自己的后退按钮,使其比标准的网络浏览器后退按钮更大、更漂亮。

    在后台你的代码可以知道之前的状态是什么并恢复到它,或者如果没有之前的状态你可以调用浏览器的返回函数?

    【讨论】:

    • 感谢您的想法,我实际上已经这样做了,但是,有些用户仍然单击另一个后退按钮(有时包括我自己)。
    • 制作自己的后退按钮是一个可怕的想法 :)
    【解决方案6】:

    阻止使用后退按钮。当按下后退按钮时,为用户重新呈现包含新字段的前一页,如果有意义的话,可以显示,也可以隐藏。这样用户就可以正常使用后退按钮,并且您可以完全控制“上一个”页面的外观。

    在您的特定用例中,您只需要呈现所有可见字段并填写提交的值的页面。

    对于任何向导类型的流程来说,这是一个很好的模式,您可以提供一系列表格供用户填写,他们可以选择返回到以前的表格。

    为了清楚起见,我建议您使用this advice on capturing the onUnload event 来触发表单提交(以便您获取输入的值)并重新呈现“返回”将显示的上一页(没有值)。唯一的替代方法是每次用户离开字段时使用 Ajax 发送输入的值,然后通过 AJAX 与服务器检查每个页面以检索要显示的其他值。

    这里有一些额外的页面讨论了控制后退按钮的功能并使用 unload 事件来持久化表单数据:

    【讨论】:

    • 这里的问题是..如何使用用户提交的值重新呈现上一页。并且不要忘记用户可以更改值并再次提交。他们甚至可能会删除一些值。
    • 奇怪的评论。服务器上的应用程序具有用户提交的值,并且应该知道如何使用用户提交的附加值重新呈现前一页(它也呈现)。或被用户删除。关键是,点击提交后,状态存在于服务器中,如果它想在用户查看的页面上保持该状态,它可以渲染包含该状态的页面,以便该状态现在在客户端上。
    猜你喜欢
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    相关资源
    最近更新 更多