Javascript:如何暂时禁用页面上的所有操作?

时间:2009-04-20 08:27:54

标签: javascript events

在具有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> &nbsp;
<input type="button" value="button action" onclick="alert('This is another action!')"/>
</body>
</html>

谢谢你们的想法和答案。

现在我看到我混淆了字符串和函数,这显然无法工作;(

我应该明确表示我们使用一些Web FW和标记库(Trinidad)来创建事件处理(和Ajax)代码,因此我无法直接编辑它或使用同步Ajax等。

此外,Ajax只是应该执行此代码的一种情况。它的目的是阻止用户双重提交页面/操作,这也与非Ajax页面相关,您可以在其中点击按钮。我知道这不是很安全,并且只是为了避免过于频繁地获取导航错误页面,这只是一个“方便”的东西(我们当然有服务器端保护)。

所以,可能会尝试div叠加。

再次感谢,
克里斯托弗。

6 个答案:

答案 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>标签),然后按回车键,仍会导致双重提交。