2016-02-19 129 views
1

在用戶瀏覽頁面代碼之前,檢查他是否編輯了一些表單域。如果他這樣做,我會顯示一個帶有YesNo按鈕的模式窗口。如果他點擊否,模式應該關閉並且用戶保持在該窗口上。如果是 - 保存更改並卸載。停止頁面在beforeunload事件處理程序中卸載

$(window).bind('beforeunload', function(){ 
     // check if any field is dirty 
     if ($('div.form').dirtyForms('isDirty')) { 
      var modalParams = { 
       Content: 'You have some unsaved changes, proceed?' 
       OnSave: navigateAndSave, 
       OnCancel: cancelNavigate 
      } 
      ShowModal(modalParams); 
     } 
    }) 

function navigateAndSave() { 
    // Do stuff 
}; 

function cancelNavigate() { 
    // Stop page from unloading and close the modal 
}; 

那麼我能在cancelNavigate上做些什麼來阻止頁面的卸載?

+0

在將來,如果您對jQuery的骯髒的形式有任何疑問,您應該包括在問題jQuery的dirtyforms標籤讓你更容易獲得足夠的答案。 – NightOwl888

回答

-1

我相信你只需要在事件中調用preventDefault。

$(window).bind('beforeunload', function(e){ 
     // check if any field is dirty 
     if ($('div.form').dirtyForms('isDirty')) { 
      var modalParams = { 
       Content: 'You have some unsaved changes, proceed?' 
       OnSave: navigateAndSave, 
       OnCancel: e.preventDefault(); 
      } 
      ShowModal(modalParams); 
     } 
    }) 

function navigateAndSave() { 
    // Do stuff 
}; 
0

這是不可能的。

您僅限於顯示文本消息以及在頁面上繼續或離開的選項。

請,看到此鏈接以獲取更多信息:https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload

window.onbeforeunload = funcRef 
  • funcRef是一個函數或功能表達的引用。
  • 函數應該爲Event對象的returnValue屬性指定一個字符串值並返回相同的字符串。

例子:

window.onbeforeunload = function(e) { 
    return 'Dialog text here.'; 
}; 

可以,之後用戶決定留在頁面上,顯示你的語氣,但我認爲它的建議將在那時被擊敗。

如其他人所述,您可以通過監聽頁面上鍊接和窗體上的點擊和鍵盤事件來攔截導航,但是當用戶嘗試手動輸入URL時,不會顯示任何對話框,請關閉選項卡,關閉窗口,按下重新加載,後退或前進按鈕等。

beforeunload事件被設計爲這種方式來保護用戶免受惡意腳本攻擊。

如果允許某種控制,某人可以將瀏覽器鎖定在所需的頁面中,但不允許您導航或關閉該窗口。

編輯:

我已經成功地顯示一個確認對話框,作品幾乎要通過連接到2個事件beforeunloadunload以同樣的方式。它的工作原理上的Internet Explorer 11,火狐40和Safari 5.1的Windows(我現在能確認):

var alreadyTriggered = false; 
 

 
function onQuit() { 
 
    if (alreadyTriggered) return true; 
 
    alreadyTriggered = true; 
 

 
    if (confirm('Sure?')) { 
 
    alert('OK'); 
 
    } else { 
 
    alert('Cancel'); 
 
    } 
 
} 
 

 
window.onbeforeunload = onQuit; 
 
window.onunload = onQuit;
You can <a href="javascript: location.reload();">reload the page</a> to test it here.

這依賴於對JS事件循環中斷的確認對話框原因,並且無法使用自定義對話框進行此項工作,因爲在用戶獲得與其交互的機會之前,頁面將會更改或關閉。

仍然沒有辦法避免頁面更改或關閉,也無法使其在Chrome中運行。這在Firefox中也不起作用,事件不是由用戶交互觸發的。

+0

是它在某種程度上可以援引「離開此頁面」,並自動取消這樣呢? – Mefhisto1

+0

不幸的是,這也是不可能的。請記住,所有這些限制都是內涵安全措施。 – rcdmk

+0

Downvoting這一點,因爲這是可能的骯髒的形式,它只是不與'beforeunload'事件可能。在用戶嘗試通過單擊頁面內的超鏈接來導航的情況下,髒表單能夠顯示GUI模式對話框。 – NightOwl888

2

這是可能的,但只有當用戶單擊頁面內的超鏈接。如果用戶使用瀏覽器遠離頁面,他們將得到默認瀏覽器對話框,該對話框沒有保存選項。

骯髒的形式自動連接(和刪除處理)到beforeunload事件,讓你嘗試創建另一個事件處理程序肯定會失敗。使用髒表單時,絕不應該這樣做。

你沒有提到你想要使用哪種模式對話框框架,所以我只會使用jQuery UI對話框來展示一個例子。集成其他對話框框是類似的。爲此,您可能需要查看existing pre-built dialogs的源代碼。

此外,您的用例有點短。如果用戶想要導航並忽略這些更改會怎麼樣?我添加了一個包含額外選項的示例。

<html> 
<head> 
    <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.ui/1.11.3/jquery-ui.min.css" /> 
</head> 
<body> 

    <script type="text/javascript" src="//cdn.jsdelivr.net/g/[email protected],[email protected],[email protected]"></script> 
    <script type="text/javascript"> 
    $(document).ready(function() { 
     // This is required by jQuery UI dialog 
     $('body').append('<div id="dirty-dialog" style="display:none;" />'); 

     // This must be called before the first call to .dirtyForms 
     $(document).bind('bind.dirtyforms', function (ev, events) { 
      var originalOnRefireClick = events.onRefireClick; 

      events.onRefireClick = function (ev) { 
       if (saveForm) { 
        // TODO: Replace this with your AJAX function 
        // to save the form. 
        alert('saving form...'); 
       } 
       originalOnRefireClick(ev); 
      }; 
     }); 

     // Flag indicating whether or not to save the form on close. 
     var saveForm = false; 

     $('.mainForm').dirtyForms({ 
      dialog: { 
       // Custom properties to allow overriding later using 
       // the syntax $.DirtyForms.dialog.title = 'custom title'; 

       title: 'Are you sure you want to do that?', 
       proceedAndSaveButtonText: 'Save Changes & Continue', 
       proceedAndCancelButtonText: 'Cancel Changes & Continue', 
       stayButtonText: 'Stay Here', 
       preMessageText: '<span class="ui-icon ui-icon-alert" style="float:left; margin:2px 7px 25px 0;"></span>', 
       postMessageText: '', 
       width: 650, 

       // Dirty Forms Methods 
       open: function (choice, message) { 
        $('#dirty-dialog').dialog({ 
         open: function() { 
          // Set the focus on close button. This takes care of the 
          // default action by the Enter key, ensuring a stay choice 
          // is made by default. 
          $(this).parents('.ui-dialog') 
            .find('.ui-dialog-buttonpane button:eq(2)') 
            .focus(); 
         }, 

         // Whenever the dialog closes, we commit the choice 
         close: choice.commit, 
         title: this.title, 
         width: this.width, 
         modal: true, 
         buttons: [ 
          { 
           text: this.proceedAndSaveButtonText, 
           click: function() { 
            // Indicate the choice is the proceed action 
            choice.proceed = true; 

            // Pass a custom flag to indicate to save the data first 
            // in the onRefireClick event 
            saveForm = true; 

            $(this).dialog('close'); 
           } 
          }, 
          { 
           text: this.proceedAndCancelButtonText, 
           click: function() { 
            // Indicate the choice is the proceed action 
            choice.proceed = true; 
            // Pass a custom flag to indicate not to save the data 
            // in the onRefireClick event 
            saveForm = false; 

            $(this).dialog('close'); 
           } 
          }, 
          { 
           text: this.stayButtonText, 
           click: function() { 
            // We don't need to take any action here because 
            // this will fire the close event handler and 
            // commit the choice (stay) for us automatically. 
            $(this).dialog('close'); 
           } 
          } 
         ] 
        }); 

        // Inject the content of the dialog using jQuery .html() method. 
        $('#dirty-dialog').html(this.preMessageText + message + this.postMessageText); 
       }, 
       close: function() { 
        // This is called by Dirty Forms when the 
        // Escape key is pressed, so we will close 
        // the dialog manually. This overrides the default 
        // Escape key behavior of jQuery UI, which would 
        // ordinarily not fire the close: event handler 
        // declared above. 
        $('#dirty-dialog').dialog('close'); 
       } 
      } 
     }); 
    }); 
    </script> 

    Change one of the fields below, then click "Go to Google" to try to navigate away. 

    <form class="mainForm" action="jqueryui.html"> 
     First name: <input type="text" name="fname"><br> 
     Last name: <input type="text" name="lname"><br> 
     <input type="submit" value="Submit"> 
    </form> 

    <a href="http://www.google.com/">Go to Google</a> 

</body> 
</html> 

的例子使用custom event binding附加到onRefireClick事件處理程序,它就會引發choice.proceed = true,但是當它是false不是。