2012-08-01 142 views
25

我正在使用window.onbeforeunload來防止用戶在更改表單上的值後導航。這工作正常,除了它還顯示用戶提交表單(不需要)時的警告。window.onbeforeunload - 僅在未提交表單時顯示警告

如何在表單提交時不顯示警告的情況下執行此操作?

當前代碼:

var formHasChanged = false; 

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) { 
    formHasChanged = true; 
}); 

$(document).ready(function() { 
    window.onbeforeunload = function (e) { 
     if (formHasChanged) { 
      var message = "You have not saved your changes.", e = e || window.event; 
      if (e) { 
       e.returnValue = message; 
      } 
      return message; 
     } 
    } 
}); 

回答

26

使用表單的提交事件來設置一個標誌,你可能工作。

var formHasChanged = false; 
var submitted = false; 

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) { 
    formHasChanged = true; 
}); 

$(document).ready(function() { 
    window.onbeforeunload = function (e) { 
     if (formHasChanged && !submitted) { 
      var message = "You have not saved your changes.", e = e || window.event; 
      if (e) { 
       e.returnValue = message; 
      } 
      return message; 
     } 
    } 
$("form").submit(function() { 
    submitted = true; 
    }); 
}); 
+0

我接受了@ Derek的這個,因爲我已經有自定義提交代碼,需要分別檢查兩個值。 – mtmurdock 2012-08-01 21:15:56

10

您可以處理submit()事件,這隻會發生於您的表單提交。

在該事件中,將您的標誌變量formHasChanged設置爲false以允許卸載繼續。此外,只是一個建議,但由於該標誌變量的目的將發生變化,所以你可能要重新命名它像「warnBeforeUnload」

$(document).submit(function(){ 
    warnBeforeUnload = false; 
}); 
11

你可以使用。對()來onbeforeunload綁定,然後使用.off()來解除綁定的表單提交

$(document).ready(function() { 
    // Warning 
    $(window).on('beforeunload', function(){ 
     return "Any changes will be lost"; 
    }); 

    // Form Submit 
    $(document).on("submit", "form", function(event){ 
     // disable warning 
     $(window).off('beforeunload'); 
    }); 
} 
2

我一直在尋找一個更好的解決了這一點。我們想要的只是排除一個或多個觸發器來創建我們的「你確定嗎?」對話框。所以我們不應該爲越來越多的副作用創造越來越多的解決方法。如果提交表單沒有提交按鈕的事件click怎麼辦?如果我們的點擊處理程序刪除isDirty狀態,但之後表單提交被阻止,該怎麼辦?當然,我們可以改變觸發器的行爲,但正確的地方是處理對話的邏輯。綁定到窗體的submit事件,而不是綁定到提交按鈕的click事件是這個線程的答案在上面的一些其他人看到的優勢之前,但這個恕我直撥只是修復了錯誤的方法。

經過在onbeforeunload事件的事件對象中進行了一些挖掘之後,我發現.target.activeElement屬性包含最初觸發事件的元素。所以,是的,它是按鈕或鏈接,或者我們點擊的任何東西(或者,如果瀏覽器本身導航離開)。我們的「你確定嗎?」對話邏輯則本身降低到以下兩個部分組成:

  1. isDirty處理形式:「你確定」

    $('form.pleaseSave').on('change', function() { 
        $(this).addClass('isDirty'); 
    }); 
    
  2. 的對話邏輯:

    $(window).on('beforeunload', function(event) { 
        // if form is dirty and trigger doesn't have a ignorePleaseSave class 
        if ($('form.pleaseSave').hasClass('isDirty') 
         && !$(event.target.activeElement).hasClass('ignorePleaseSave')) { 
        return "Are you sure?" 
        } 
        // special hint: returning nothing doesn't summon a dialog box 
    }); 
    

它只是作爲。沒有必要的解決方法。只需給觸發器(提交和其他動作按鈕)一個ignorePleaseSave類和我們想要將對話框應用於pleaseSave類的表單。卸載該頁面的所有其他原因然後召喚我們的「你確定嗎?」對話。

P.S.我在這裏使用jQuery,但我認爲.target.activeElement屬性也可以在普通的JavaScript中使用。

+0

這似乎是瀏覽器特定的。在Chrome中運行良好,但Firefox中的目標始終是'body' – 2015-09-16 04:04:56

+0

剛剛在Firefox 40中進行了測試,event.target.activeElement實際上提供了時鐘元素,就像它在Chrome中一樣。我的解決方案適用於兩種瀏覽器。 – spackmat 2015-09-16 08:23:32

+0

我喜歡這種方法,但我無法在IE中使用它。但完全忽略事件並使用document.activeElement爲我做了竅門(目前爲止只在Chrome和IE中測試過) – Doogal 2016-09-13 12:07:49