提问人:Chris 提问时间:11/23/2012 更新时间:8/17/2019 访问量:8691
jQuery表单发布返回后如何触发事件?
jQuery how to trigger event after form post returns?
问:
我有一个昂贵的表单操作,它在服务器上构建一个 zip 文件并将其返回到浏览器。
<form action='/download' method='post'>
<input type='submit' value='download'/>
</form>
我想在单击按钮时阻止该页面,以便用户不会重复点击该按钮。
但是,我想在表单返回后取消阻止该页面。
如何在成功填写表单时触发事件?
(我知道我可以通过将表单更改为ajax提交来触发它,但是没有出现保存文件对话框......
有什么建议吗?
谢谢
答:
5赞
Kyle
11/23/2012
#1
在不使用 AJAX 的情况下处理此问题的一种方法是将表单的内容提交到元素。如果将 onsubmit 函数附加到禁用进一步提交的表单,并将 onload 函数附加到 iframe,则应该能够禁止用户多次提交表单。iframe
HTML 示例:
<form action="/download" method="post" target="downloadFrame" onsubmit="return downloadFile();">
<input type="submit" value="download" />
</form>
<iframe style="width: 0px; height: 0px;" scrolling="no" frameborder="0" border="0" name="downloadFrame" onload="downloadComplete();"></iframe>
示例 Javascript:
var downloading = false;
function downloadFile() {
var isDownloading = downloading;
downloading = true;
return !isDownloading;
}
function downloadComplete() {
downloading = false;
}
评论
1赞
Chris
11/23/2012
我相信 onsubmit 是在提交时触发的,而不是在完成提交操作时触发的。
0赞
Kyle
11/23/2012
@Chris 你是对的。这将处理进一步的提交。我忘记了当文件下载发生时,页面不会重新加载。我会尽快更新我的答案。
0赞
Chris
11/24/2012
这确实有效,但远非理想,在某些错误条件下,我的操作将使用消息进行 301 重定向,使用隐藏的 iframe,这完全丢失了,对用户来说似乎什么也没发生。此外,我没有看到将函数绑定到 iframe 的加载事件的好方法,而是像您所做的那样,我需要 iframe 调用包含文档中的函数,这意味着污染全局命名空间。所以我想我会放弃这种方法,并将下载作为 2 步过程进行。谢谢你的黑客,希望有人会发现它有用!
0赞
Kyle
11/24/2012
@Chris 是的,由于多种原因,这远非理想,但这是将其作为完整的 1 步过程的唯一方法之一。如果您不想使用内联函数,则始终可以使用 jQuery 将函数加载到 iframe。另一种方法可能是在表单上使用的新窗口中打开提交。bind
target="_blank"
0赞
Arno Schäfer
8/6/2013
#2
似乎还没有人找到一种方法来检测浏览器本身的帖子返回,但还有另一种可能性使用 AJAX。不过,它更复杂一些:
<script type="text/javascript">
$(function () {
$('#submitbtn').click (function () {
window.setTimeout (dldone, 100);
return true;
});
function dldone () {
$.get ("/downloadstatus?rand="+$('#rand').val (), function (data) {
if (data == 'done') {
// data generation finished, do something
} else {
window.setTimeout (dldone, 100);
}
});
}
});
</script>
<form action="/generatedata" method="post">
<input type="hidden" id="rand" value="[RANDOMVALUE]">
<input type="submit" id="submitbtn" value="Download Data">
</form>
在服务器上,您必须进行一些进程间通信,以在数据生成完成时发出信号。由于我已经有一个数据库,所以我这样做了:
public function downloadstatusAction () {
if ($this->db->fetchOne ("SELECT rand FROM dlstatus WHERE rand = ?", (int) $_GET["rand"])) {
$db->delete ("dlstatus", array ("rand = ?" => (int) $_GET["rand"]));
print "done";
} else {
print "loading";
}
}
public function generatedataAction () {
// generate data
$this->db->insert ("dlstatus", array ("rand" => (int) $_POST["rand"]));
// output data
}
我相信有更优雅的方法可以做到这一点,但你明白了。这似乎在我测试的所有浏览器中都能正常工作。
0赞
petro
11/28/2014
#3
我用了这个:
function generatePdfZipViaWS_ajax(theUrl) {
//=========================
// testé avec Chrome 37.0.2062.124 m, Firefox 32.0.3
// ça block avec IE9 à cause du xmlHttp.overrideMimeType
//=========================
var xmlHttp = new XMLHttpRequest();
var alert = document.getElementById("alertError");
block_UI();
var url = "undefined";
xmlHttp.open("GET", theUrl, true);
xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlHttp.overrideMimeType("application/octet-stream");
xmlHttp.responseType = "blob";
xmlHttp.onload = function(oEvent) {
if (xmlHttp.status == 200) {
deblock_UI();
// a mettre apres un certain temps: window.URL.revokeObjectURL(url);
} else {
alert.style.display = "block";
deblock_UI();
// console.log("Error " + xmlHttp.status + " occurred downloading your file.<br \/>");
}
};
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == xmlHttp.DONE) {
if (xmlHttp.status == 200) {
var contentDisposition = xmlHttp.getResponseHeader("Content-Disposition");
var type = xmlHttp.getResponseHeader("Content-Type");
var reponseType = xmlHttp.responseType;
var pos1 = contentDisposition.indexOf("archive");
var pos2 = contentDisposition.lastIndexOf(".zip") + 4;
var fileName = contentDisposition.substring(pos1, pos2);
if (fileName === null) {
fileName = "archivexxxxxxxxxxxxxx.zip";
}
console.log("fileName:" + fileName);
var blob = xmlHttp.response;
url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.style = "display: none";
a.href = url;
a.download = fileName;
a.type = type;
document.body.appendChild(a);
a.click();
//a.delete();
deblock_UI();
} else {
var msg =" Une erreur " + xmlHttp.status +" est apparue pendant que votre demande était traitée.\n"
msg = msg + "Merci de réessayer plus tard!";
alert.innerHTML = msg;
alert.style.display = "block";
deblock_UI();
console.log(msg);
}
}
};
xmlHttp.send();
}
评论
0赞
petro
11/29/2014
IE et Safari var a = document.createElement('a');var wasPageHide = 0;a.cssText= “显示:无”;a.href = 网址;document.body.appendChild(a);if (is_safari === true ){ var evObj = document.createEvent('MouseEvents'); evObj.initMouseEvent('click', true, true, window); a.dispatchEvent(evObj); }else{ a.click(); } if(window.addEventListener){ window.addEventListener('focus', deblock_UI, false);else{ window.attachEvent('onfocus',deblock_UI);
0赞
PJ Brunet
8/17/2019
#4
我现在没有时间写一个正确的答案,但由于没有其他人有好的答案,我认为“突变观察者”会起作用......https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
评论