避免形成多个提交并在完成后重新启用

我有一个表单,允许查看页面中的数据或根据按下的提交按钮在csv中下载。

由于这是一个很长的数据库查询,我想避免用户多次提交(你知道用户的食指在鼠标左键上有多重……)以避免数据库过载并使用户更轻松…

我写了这个小jQuery代码来替换提交按钮和处理,请等待和经典的动画旋转gif

$(document).ready(function(){ //preload wait img var $waitImg = $('').attr('src', '/img/wait.gif') $('.wait').click(function(){ $(':submit').hide(); $(this).after($('Processing, please wait...').prepend($waitImg)); }); }); 

所有的工作,但有一些缺点:

  • 当用户看到结果然后按下浏览器的后退按钮时,他将再次获得处理,请等待句子并且没有提交按钮(如果他只想编辑某些内容并进行新查询,该怎么办)
  • 在提示用户下载CSV文件后,他继续被告知要等待…

解决方案可能是检测某些用户回来或下载盯着或以其他方式告诉他工作正在进行中。

越容易越好。

当用户看到结果然后按浏览器的后退按钮时,他将再次获得处理,请等待句子并且没有提交按钮(如果他只想编辑某些内容并进行新查询,该怎么办)

浏览器正在缓存页面。 您可以尝试重置值/删除$(document).ready()的加载图像,当用户使用onunload技巧按下后退按钮时应该触发: 单击后退按钮时是否存在跨浏览器onload事件?

在提示用户下载CSV文件后,他继续被告知要等待…

没有服务器的帮助,将无法检测到这一点。 最简单的方法是通过ajax“ping”服务器,服务器将告诉客户端下载是否已启动/发送给用户。 这可以通过重复性每隔3秒调用服务器来查看是否已启动下载,如果是,则重置/隐藏加载图像和文本。

您可以使用延迟的jQuery来帮助实现这一简单和良好的语法。

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 / Server端

在服务器端,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

 
...

JavaScript的

 $(document).ready(function(){ var cookieCheckTimer; var cookieName = 'download_token'; var $wait = $('.wait'); var $waitMsg = $('Processing, please wait...').prepend( $('').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($('').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( __before__ )代码:

python

 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并恢复按钮。