2009-08-05 55 views
12

在我的ASP.NET Web應用程序中,我試圖創建一種通用的方式來警告用戶,然後再導入表單jQuery的。相當標準的東西,但經過大量的搜索,我還沒有找到一種可行的技術。ASP.NET,jQuery,髒表單和window.onbeforeunload

這裏是我在這一點上:

addToPostBack = function(func) { 
     var old__doPostBack = __doPostBack; 
     if (typeof __doPostBack != 'function') { 
      __doPostBack = func; 
     } else { 
      __doPostBack = function() { 
       old__doPostBack(); 
       func(); 
      } 
     } 
    } 

    var isDirty = false; 

    $(document).ready(function() { 
     addToPostBack(function() { 
      alert("Postback detected.") 
      clearDirty(); 
     }); 
     $(':input').bind("change select keydown", setDirty); 
     window.onbeforeunload = function(e) { 
      var msg = "You have unsaved changes. " 
      if (isDirty == true) { 
       var e = e || window.event; 
       if (e) { e.returnValue = msg; } 
       return msg; 
      } 
     }; 
    }); 

    setDirty = function() {isDirty = true;} 

    clearDirty = function() {isDirty = false;} 

這工作就從警告離開頁面的用戶。問題是我在每個相同頁面的回發中收到警告。有一些關於我的形式的東西,可能會觸發回發:

  1. 有保存,取消,並在頁面上刪除了LinkBut​​ton
  2. 有可能是頁面上的其他了LinkBut​​ton是執行服務器端功能同時停留在同一頁面
  3. 可能還有其他autopostback = true的控件也具有附加的服務器端功能,但不會導致用戶離開頁面。

這些東西都不會引發警告,因爲用戶不會離開頁面。我的代碼嘗試劫持addToPostBack(more details on that in this question)以在回發之前清除isDirty位,但問題在於IE_onbeforeunload在__doPostBack之前觸發,顯然是因爲IE在單擊鏈接時立即在未加載的情況下觸發(as described here)。

當然,我可以連接這些控件中的每一個來清除isDirty位,但我更喜歡在表單級別上運行的解決方案,並且不需要我觸摸每一個可能觸發回發。

有沒有人有辦法在ASP.NET中工作,並不涉及每個控件可能會導致回發?

+0

你可以只是作弊和檢查SO源代碼,看看他們做什麼。 – Powerlord 2009-08-05 18:49:52

+1

SO使用beforeunload之前,但它的MVC ==沒有回傳==沒有Herb的特殊問題。 – 2009-08-05 19:08:57

回答

2

你總是可以創建一個不受約束的頁面類,該類有一個定製的OnLoad/OnUnload方法,可以立即執行javascript。

然後,您不必在控件特定級別處理它,而是在表單/頁面級別處理它。

+0

不清楚你的建議。這個方法/方法會做什麼? – 2009-08-05 20:14:00

2

有趣,但...爲什麼你不用jQuery做所有事情?現在

var defaultSubmitControl = false; 
var dirty = false; 
$(document).ready(function() { 
    $('form').submit(function() { dirty = false }); 
    $(window).unload(function() { 
     if (dirty && confirm('Save?')) { 
      __doPastBack(defaultSubmitControl || $('form :submit[id]').get(0).id, ''); 
     } 
    }); 
}); 
··· 
dirty = true; 
··· 

,如果還是引起了同樣的問題(unloadsubmit之前觸發),你可以嘗試不同的事件樹,所以不是叫__doPostBack直接做什麼...

setTimeout(function() { 
    __doPastBack(defaultSubmitControl || $('form :submit[id]').get(0).id, ''); 
}, 1); // I think using 0 (zero) works too 

我沒有試過這個,它是從我的頭頂開始的,但我認爲這可能是一種解決問題的方法。

0

我也在尋找這個,但我發現到目前爲止,使用所有html控件而不是asp.net網絡控件的解決方案,你有沒有想到這一點?

<script type="text/javascript"> 
    $(document).ready(function() { 
     $("form").dirty_form(); 
     $("#btnCancel").dirty_stopper(); 
    });    
    </script> 
1

通過基本跟蹤鼠標位置得到這個工作。請記住,您的Y值仍然可以獲得正值(因此我的代碼行數爲正值),但只要您的提交按鈕超過100個像素,就應該沒問題。

這裏是JavaScript我加入到跟蹤鼠標的變化和捕捉onbeforeunload事件:

<script language="JavaScript1.2"> 
    <!-- 

    // Detect if the browser is IE or not. 
    // If it is not IE, we assume that the browser is NS. 
    var IE = document.all?true:false 

    // If NS -- that is, !IE -- then set up for mouse capture 
    if (!IE) document.captureEvents(Event.MOUSEMOVE) 

    // Set-up to use getMouseXY function onMouseMove 
    document.onmousemove = getMouseXY; 

    // Temporary variables to hold mouse x-y pos.s 
    var tempX = 0 
    var tempY = 0 

    // Main function to retrieve mouse x-y pos.s 

    function getMouseXY(e) { 
     if (IE) { // grab the x-y pos.s if browser is IE 
     tempX = event.clientX + document.body.scrollLeft 
     tempY = event.clientY + document.body.scrollTop 
     } else { // grab the x-y pos.s if browser is NS 
     tempX = e.pageX 
     tempY = e.pageY 
     } 
     // catch possible negative values in NS4 
     if (tempX < 0){tempX = 0} 
     if (tempY < 0){tempY = 0} 
     // show the position values in the form named Show 
     // in the text fields named MouseX and MouseY 
     document.Show.MouseX.value = tempX 
     document.Show.MouseY.value = tempY 
     return true 
    } 

    //--> 
    </script> 


    <script type="text/javascript"> 

     window.onbeforeunload = HandleOnClose; 

     function HandleOnClose(e) { 

      var posY = 0; 
      var elem = document.getElementsByName('MouseY'); 
      if (elem[0]) { 
       posY = elem[0].value; 
      } 

      if (posY < 50) { // Your form "submit" buttons will hopefully be more than 100 pixels down due to movement 
       return "You have not selected an option, are you sure you want to close?"; 
      } 
     } 

    </script> 

然後,只需添加下面的表格到您的網頁:

<form name="Show"> 
     <input type="hidden" name="MouseX" value="0" size="4"> 
     <input type="hidden" name="MouseY" value="0" style="display:block" size="0"> 
    </form> 

就是這樣!它可以使用一些清理(刪除MouseX等),但這在我現有的ASP.net 3.5應用程序中工作,並認爲我會發布以幫助任何人。適用於IE 7和Firefox 3.6,還沒有試用過Chrome。

8

我遇到這篇文章,同時谷歌搜索一個解決方案在MVC做同樣的事情。這個解決方案,改編自上面的Herb,似乎運作良好。由於沒有什麼特定於MVC的內容,所以對於PHP,經典ASP或任何其他類型的使用HTML和JQuery的應用程序來說,它應該也是一樣。

​​