簡體   English   中英

Javascript:如何暫時禁用頁面上的所有操作?

[英]Javascript: How to temporarily disable all actions on the page?

在帶有 Ajax 事件的頁面上,我想禁用所有操作,直到 Ajax 調用返回(以防止重復提交等問題)

我通過預先設置return false;嘗試這個return false; “鎖定”頁面時的當前 onclick 事件,稍后在“解鎖”頁面時將其刪除。 但是,這些操作在“解鎖”后不再處於活動狀態——您只是無法觸發它們。

為什么這不起作用? 請參閱下面的示例頁面。 還有其他想法可以實現我的目標嗎?

示例代碼:
鏈接和按鈕都顯示 JS 警報; 當按下鎖定時,則解鎖事件處理程序與之前相同,但不起作用......?!?
該代碼旨在最終與 Trinidad 一起使用,但也應該在外部使用。

<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>

謝謝你們的想法和答案。

現在我看到我把字符串和函數搞混了,這顯然是行不通的;(

我應該明確指出我們使用了一些創建事件處理(和 Ajax)代碼的 Web FW 和標記庫(Trinidad),因此我無法直接編輯它們或使用同步 Ajax 等。

而且,Ajax 只是應該執行此代碼的一種場景。 它的目的是防止用戶重復提交頁面/操作,這也與非 Ajax 頁面相關,您可以在其中雙擊按鈕。 我知道這並不是真的安全,它只是為了避免過於頻繁地獲取導航錯誤頁面(當然,我們有服務器端保護)是一種“方便”的東西。

所以,可能會嘗試 div 覆蓋。

再次感謝,
克里斯托夫。

如何設置一個全局變量

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

我曾經通過創建一個覆蓋我想要禁用的區域的 DIV 來實現這個目標,將其z-index設置為高於頁面上任何其他元素,然后將其opacity設置為0 默認情況下,這個 DIV 被display: none隱藏,這樣它就不會干擾任何東西。 但是,當我想要禁用該區域時,我只需將其display設置為block

史蒂夫

將 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();
    
},

阿賈克斯。 異步。 只需使 HTTP 請求同步即可。 問題解決了。

您的代碼的問題是因為沒有掌握 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。

使用 div 覆蓋不會阻止用戶通過 Tab 鍵進入您的頁面。 通常這是可以的,因為大多數用戶無論如何都不會瀏覽頁面。

如果您在頁面上使用任何鍵盤快捷鍵,它們仍然可用,因此需要對它們進行單獨處理。

另外,我假設單擊可以具有焦點的元素(例如<a>標簽),然后按 Enter 鍵,仍然會導致雙重提交。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM