ASP.NET、jQuery、脏表单和window.onbeforeunload

ASP.NET、jQuery、脏表单和window.onbeforeunload,asp.net,jquery,onbeforeunload,Asp.net,Jquery,Onbeforeunload,在我的ASP.NET web应用程序中,我试图创建一种通用的方法,在用户进行更改之前,使用jQuery警告他们离开表单。相当标准的东西,但经过大量的搜索,我还没有找到一种有效的技术 以下是我目前的情况: addToPostBack = function(func) { var old__doPostBack = __doPostBack; if (typeof __doPostBack != 'function') { __doPo

在我的ASP.NET web应用程序中,我试图创建一种通用的方法,在用户进行更改之前,使用jQuery警告他们离开表单。相当标准的东西,但经过大量的搜索,我还没有找到一种有效的技术

以下是我目前的情况:

    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;}
这可以警告用户不要离开。问题是我在每次回发的同一页上都会收到警告。我的表单上有很多东西可能会触发回发:

  • 页面上有保存、取消和删除链接按钮
  • 页面上可能有其他链接按钮,在保持在同一页面上的同时执行服务器端功能
  • 可能还有其他autopostback=true的控件也附加了服务器端函数,但不会导致用户离开页面 所有这些都不应该引起警告,因为用户没有离开页面。我的代码试图劫持AddTopoPostBack()以在发回之前清除isDirty位,但问题是在IE中,
    onbeforeunload
    在doPostBack之前触发,显然是因为IE在单击链接时立即触发onbeforeunload()

    当然,我可以连接这些控件以清除isDirty位,但我更喜欢在表单级别操作的解决方案,它不需要我接触可能触发回发的每个控件


    是否有人有一种方法可以在ASP.NET中工作,并且不涉及连接可能导致回发的每个控件?

    您可以始终创建一个继承的页面类,该类具有一个自定义的
    OnLoad
    /
    OnUnload
    方法,该方法添加到即时执行JavaScript中


    然后,您不必在特定于控件的级别上处理它,而是在表单/页面级别上处理它。

    很有趣,但是。。。为什么不使用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;
    ···
    
    现在,如果这仍然导致相同的问题(
    unload
    submit
    之前触发),您可以尝试另一个事件树,而不是直接调用
    \u doPostBack

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

    我还没有尝试过,这是我的想法,但我认为这可能是一种解决方法。

    我也在考虑这个问题,但到目前为止我发现的是,一种使用所有html控件而不是asp.net web控件的解决方案,你想过吗

      <script type="text/javascript">
        $(document).ready(function () {
          $("form").dirty_form();
          $("#btnCancel").dirty_stopper();
        });             
      </script>
    
    
    $(文档).ready(函数(){
    $(“形式”).dirty_form();
    $(“#btnCancel”).dirty_stopper();
    });             
    
    基本上是通过跟踪鼠标位置实现的。请记住,您仍然可以获得Y值的正值(因此我的代码<50行),但只要提交按钮向下超过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>
    
    
    window.onbeforeuload=HandleOnClose;
    功能关闭(e){
    var-posY=0;
    var elem=document.getElementsByName('MouseY');
    if(元素[0]){
    posY=elem[0]。值;
    }
    如果(posY<50){//由于移动,您的表单“提交”按钮有望减少100多个像素
    return“您尚未选择选项,是否确实要关闭?”;
    }
    }
    
    然后,只需在页面上添加以下表单:

        <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.NET3.5应用程序中起作用,我想我会发布文章来帮助任何人。适用于IE 7和Firefox 3.6,还没有试用过Chrome。

    我在谷歌上搜索MVC的解决方案时发现了这篇文章。这个解决方案,从赫伯的上述改编,似乎工作得很好。因为MVC对此没有什么特别之处,所以它应该同样适用于PHP、经典ASP或任何其他使用HTML和JQuery的应用程序

    var isDirty = false;
    
    $(document).ready(function () {
        $(':input').bind("change select keydown", setDirty);
        $('form').submit(clearDirty);
    
        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; }
    

    你可以作弊并检查SO源代码,看看它们做了什么。SO在卸载前使用,但MVC==无回发==没有Herb的特殊问题。不清楚你的建议是什么。这个方法会做什么?