避免表单多个提交,并在完成后重新启用
Avoid form multiple submissions and re-enable when done
我有一个表格,允许查看页面中的数据或根据按下的提交按钮以csv格式下载数据。
由于这是一个很长的数据库查询,我想避免用户多次提交(你知道用户食指在鼠标左键上的重量......)以避免数据库过载,也让用户更放松......
我写了这个小jQuery代码来替换提交按钮与处理,请稍候和经典的动画旋转gif
$(document).ready(function(){
//preload wait img
var $waitImg = $('<img />').attr('src', '/img/wait.gif')
$('.wait').click(function(){
$(':submit').hide();
$(this).after($('<span>Processing, please wait...</span>').prepend($waitImg));
});
});
所有工作都有效,但有一些缺点:
- 当用户看到结果然后按浏览器的后退按钮时,他将再次获得处理,请等待句子,没有提交按钮(如果他只想编辑某些内容并进行新查询怎么办)
- 在提示用户下载CSV文件后,他一直被告知等待...
解决方案可能是检测用户是否回来或下载凝视或其他方式告诉他工作正在进行中。
越容易越好。
当用户看到结果然后按浏览器的后退按钮时,他将再次获得处理,请等待句子,没有提交按钮(如果他只想编辑某些内容并进行新查询怎么办)
浏览器正在缓存页面。您可以尝试重置值/删除加载图像,当用户使用onunload
技巧按下后退按钮时,应该在$(document).ready()
触发该图像:单击后退按钮时是否有跨浏览器 onload 事件?
在提示用户下载CSV文件后,他一直被告知等待...
如果没有服务器的帮助,就无法检测到这一点。最简单的方法是通过ajax"ping"服务器,服务器将告诉客户端下载是否已启动/发送给用户。这可以通过重复性每 3 秒调用服务器以查看下载是否已启动来完成,如果是,则重置/隐藏加载的图像和文本。
你可以使用jQuery deferred来帮助简化这个语法。
jQuery
function downloadStarted()
{
var $def = $.Deferred();
var check = function() {
$.get('/ajax/check-download-status', function(response) {
if (response.started)
{
$def.resolve();
}
else
{
//Check again in 3 seconds
setTimeout(check, 3000);
}
}, 'json');
};
check();
return $def.promise();
}
用法:
var success = function() { /* reset/hide loading image */ }
$.when(downloadStarted()).then(success);
<小时 />PHP/服务器端
在服务器端,ajax/check-download-status 将如下所示:
session_start();
$json['started'] = 0;
if ($_SESSION['download_started']) $json['started'] = 1;
return json_encode($json);
显然,当您的csv文件发送到客户端时,请将$_SESSION['download_started']
设置为1。
找到这个:
在浏览器中检测文件下载对话框
这是我基于它的代码:
.html
<form ...>
<fieldset>
...
<div>
<input class="wait" id="submit" name="submit" type="submit" value="View" />
<input class="wait" id="submit" name="submit" type="submit" value="Download as CSV" />
</div>
</fieldset>
</form>
JavaScript
$(document).ready(function(){
var cookieCheckTimer;
var cookieName = 'download_token';
var $wait = $('.wait');
var $waitMsg = $('<span>Processing, please wait...</span>').prepend(
$('<img />').attr('src', '/img/wait.gif').css({
'vertical-align': 'middle',
'margin-right': '1em'
}));
//add hidden field to forms with .wait submit
$wait.parent().each(function(){
$(this).append($('<input />').attr({
'type': 'hidden',
'name': cookieName,
'id': cookieName
}));
});
$wait.click(function(){
var token = new Date().getTime();
//set token value
$('#' + cookieName).val(token);
//hide submit buttons
$(':submit').hide();
//append wait msg
$(this).after($waitMsg);
cookieCheckTimer = window.setInterval(function () {
if ($.cookie(cookieName) == token){
//clear timer
window.clearInterval(cookieCheckTimer);
//clear cookie value
$.cookie(cookieName, null);
//detach wait msg
$waitMsg.detach();
//show again submit buttons
$(':submit').show();
}
}, 1000);
});
});
服务器端如果在请求参数中找到download_token
键,则会设置带有其名称和值的cookie。
这是我的控制器__before__
的python(pylons)代码:
蟒
cookieName = 'download_token'
#set file download coockie if asked
if cookieName in request.params:
response.set_cookie(cookieName,
#str: see http://groups.google.com/group/pylons-discuss/browse_thread/thread/7d42f3b28bc6f447
str(request.params.get(self._downloadTokenName)),
expires=datetime.now() + timedelta(minutes=15))
我将 cookie 过期时间设置为 15 分钟,以免填满客户端 cookie,您可以根据任务所需的时间选择合适的持续时间。
这也适用于浏览器后退按钮问题,因为返回时会找到cookie并恢复按钮。
- 如何在读取XLS/XLSX本地文件时,使用IE的javascript代码启用未标记为安全的ActiveX控件
- 如何在 API 调用后和 if 语句中启用提交按钮
- 语义ui如何使用javascript启用或禁用下拉列表
- IE6在启用/禁用文本字段上闪烁
- 传单中如何在更改基层时启用/禁用覆盖层
- 根据字段的值启用按钮
- 如何使用javascript函数在gridview中按行启用/禁用复选框
- 如何禁用和启用css规则
- 淘汰赛.JS'启用'长度绑定条件不起作用
- 在新类 jQuery 上启用可拖动
- JavaScript 启用新的 HTML5 按钮属性:formaction、formmethod
- jQuery 性能问题,通过为新元素启用拖放
- Javascript——如何在不使用新运算符的情况下启用静态方法,同时防止使用实例函数
- 如何在使用窗口后启用浏览器选项卡.打开以启动一个新窗口
- 创建一个表单提交按钮,启用“在新窗中打开”;当用户右键点击时
- 检查打开新选项卡时是否启用了弹出窗口阻止程序
- 如何在加载新页面时启用jquery标签/单选按钮
- 有没有一种好方法来启用“在新窗口中打开链接”?在dom节点上的浏览器菜单选项,而不使链接跟随单击
- 如何启用超链接打开模态对话框,同时也允许在同一链接上的新选项卡中打开
- Jquery:如果其他滑动开关被启用(可见),在启动新的滑动开关之前关闭