在具有Ajax事件的页面上,我想在Ajax调用返回之前禁用所有操作(以防止双重提交等问题。)
我通过在“锁定”页面时将return false;
添加到当前的onclick事件,并在“解锁”页面时稍后删除它来尝试此操作。但是,在“解锁”后,操作不再处于活动状态 - 您无法触发它们。
为什么这不起作用?见下面的示例页面。还有其他想法来实现我的目标吗?
示例代码:
链接和按钮都显示JS警报;当按下锁定,然后解锁事件处理程序与以前一样,但不起作用......?!?
该代码最终将与特立尼达合作,但也应该在外面工作。
<html><head><title>Test</title>
<script type="text/javascript">
function lockPage()
{
document.body.style.cursor = 'wait';
lockElements(document.getElementsByTagName("a"));
lockElements(document.getElementsByTagName("input"));
if (typeof TrPage != "undefined")
{
TrPage.getInstance().getRequestQueue().addStateChangeListener(unlockPage);
}
}
function lockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.cursor = 'wait';
if (el[i].onclick)
{
var newEvent = 'return false;' + el[i].onclick;
alert(el[i].onclick + "\n\nlock -->\n\n" + newEvent);
el[i].onclick = newEvent;
}
}
}
function unlockPage(state)
{
if (typeof TrRequestQueue == "undefined" || state == TrRequestQueue.STATE_READY)
{
//alert("unlocking for state: " + state);
document.body.style.cursor = 'auto';
unlockElements(document.getElementsByTagName("a"));
unlockElements(document.getElementsByTagName("input"));
}
}
function unlockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.cursor = 'auto';
if (el[i].onclick && el[i].onclick.search(/^return false;/)==0)
{
var newEvent = el[i].onclick.substring(13);
alert(el[i].onclick + "\n\nunlock -->\n\n" + newEvent);
el[i].onclick = newEvent;
}
}
}
</script>
<style type="text/css">
</style>
</head>
<body>
<h1>Page lock/unlock test</h1>
<p>Use these actions to lock or unlock active elements on the page:
<a href="javascript:lockPage()">lock</a>,
<a href="javascript:unlockPage()">unlock</a>.</p>
<p>And now some elements:</p>
<a onclick="alert('This is the action!');return false;" href="#">link action</a>
<input type="button" value="button action" onclick="alert('This is another action!')"/>
</body>
</html>
谢谢你们的想法和答案。
现在我看到我混淆了字符串和函数,这显然无法工作;(
我应该明确表示我们使用一些Web FW和标记库(Trinidad)来创建事件处理(和Ajax)代码,因此我无法直接编辑它或使用同步Ajax等。
此外,Ajax只是应该执行此代码的一种情况。它的目的是阻止用户双重提交页面/操作,这也与非Ajax页面相关,您可以在其中点击按钮。我知道这不是很安全,并且只是为了避免过于频繁地获取导航错误页面,这只是一个“方便”的东西(我们当然有服务器端保护)。
所以,可能会尝试div叠加。
再次感谢,
克里斯托弗。
答案 0 :(得分:9)
如何设置全局变量
actions_disabled = 0
当AJAX调用开始时递增,然后在完成时递减。然后,您的所有“操作”处理程序都可以从
开始if (actions_disabled) return false;
比调试自修改代码简单得多!
或者,要锁定您的控件,您可以设置:
control.disabled="disabled"
将获得灰色奖励,使用户明显无法提交。要解锁,只需设置:
control.disabled=""
基于评论的新想法(不能在评论中引用代码,它似乎......):
您总是可以从Javascript对象中挂起额外的属性:
要锁定,你可以:
control.onclick_old = control.onclick
control.onclick = "return false;"
要解锁,你可以:
control.onclick = control.onclick_old
答案 1 :(得分:2)
我曾经通过创建涵盖我想要禁用的区域的DIV,将其z-index
设置为高于页面上的任何其他元素,然后将其opacity
设置为{{}来实现此目标1}}。默认情况下,此DIV被0
隐藏,因此不会干扰任何内容。但是,当我希望禁用该区域时,我只需将其display: none
设置为display
。
史蒂夫
答案 2 :(得分:1)
AJAX。异步。只需使HTTP请求同步即可。问题解决了。
答案 3 :(得分:1)
您的代码存在问题,因为我们没有掌握javascript中的类型。
当你说:
var newEvent = 'return false;' + el[i].onclick
这是对字符串强制el [i] .onclick(这是一个函数),然后将它连接到字符串'return false;'。然后当你重新分配它时:
el[i].onclick = newEvent;
onclick以前是一个函数,现在是一个字符串。
然后,您尝试通过获取子字符串来恢复字符串中的旧函数:
var newEvent = el[i].onclick.substring(13);
这很好,除了newEvent仍然是一个字符串!因此,当您再次将其分配回onclick时,您将分配原始函数的字符串表示形式,而不是函数本身。
您可以使用eval来评估字符串并返回函数,但请不要这样做。正如其他评论者所建议的那样,有许多更好的方法可以做到这一点。
如果你不想允许异步请求,我也会问你为什么要使用AJAX。
答案 4 :(得分:1)
将 lockPage() 放在 activete() 函数的顶部,unlockPage() 放在deactivate() 的底部。
activate: function() {
function lockPage()
{
lockElements(document.getElementsByTagName("a"));
lockElements(document.getElementsByTagName("input"));
lockElements(document.getElementsByTagName("button"));
};
function lockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.pointerEvents="none";
}
};
lockPage();
// ...
},
deactivate: function() {
// ...
function unlockPage() {
unlockElements(document.getElementsByTagName("a"));
unlockElements(document.getElementsByTagName("input"));
unlockElements(document.getElementsByTagName("button"));
};
function unlockElements(el)
{
for (var i=0; i<el.length; i++)
{
el[i].style.pointerEvents="auto";
}
};
unlockPage();
},
答案 5 :(得分:0)
使用div叠加不会阻止用户切换到您的页面。通常这没关系,因为大多数用户无论如何都不会在页面中进行制表。
如果您在页面上使用任何键盘快捷键,它们仍然可用,因此需要单独处理。
另外,我假设点击一个可以有焦点的元素(例如<a>
标签),然后按回车键,仍会导致双重提交。