12

私のASP.NETWebアプリでは、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;}

これは、ユーザーが離れないように警告する限り機能します。問題は、同じページのポストバックごとに警告が表示されることです。私のフォームには、ポストバックをトリガーする可能性のあるものがいくつかあります。

  1. ページには[保存]、[キャンセル]、[削除]のリンクボタンがあります
  2. 同じページにとどまりながらサーバー側の機能を実行する他のリンクボタンがページにある可能性があります
  3. autopostback = trueを持つ他のコントロールがあり、それらにもサーバー側の関数がアタッチされていますが、ユーザーがページを離れることはありません。

ユーザーはページを離れていないので、これらのことのどれも警告を引き起こすべきではありません。私のコードは、addToPostBack(この質問の詳細)を乗っ取って、投稿する前にisDirtyビットをクリアしようとしますが、問題は、IEonbeforeunloadでは__doPostBackの前に起動することです。これは、リンクがクリックされるとすぐにIEがonbeforeunloadを起動するためです(ここで説明します)。 )。

もちろん、これらの各コントロールを接続してisDirtyビットをクリアすることもできますが、フォームレベルで動作し、ポストバックをトリガーする可能性のあるすべてのコントロールに触れる必要がないソリューションをお勧めします。

ASP.NETで機能し、ポストバックを引き起こす可能性のあるすべてのコントロールを配線する必要のないアプローチを持っている人はいますか?

4

5 に答える 5

8

MVCで同じことを行うためのソリューションをグーグルで検索しているときに、この投稿に出くわしました。上記の Herb から適応されたこのソリューションは、うまく機能しているようです。これについては MVC 固有のものは何もないため、PHP、Classic 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; }
于 2011-02-16T23:37:32.913 に答える
2

即時実行 JavaScript を追加するカスタムOnLoad/メソッドを持つ継承されたページ クラスをいつでも作成できます。OnUnload

次に、コントロール固有のレベルではなく、フォーム/ページ レベルで処理する必要があります。

于 2009-08-05T18:52:14.753 に答える
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;
···

それでも同じ問題が発生する場合 (unload前にトリガー)、別のイベント ツリーsubmitを試すことができるので、直接呼び出す代わりに...__doPostBack

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

私はこれを試したことがなく、頭のてっぺんからですが、それを解決する方法になると思います。

于 2010-02-06T00:36:28.317 に答える
1

基本的にマウスの位置を追跡することでこれを機能させました。Y 値に対して正の値を取得できることに注意してください (したがって、私の 50 行未満のコード) が、送信ボタンが 100 ピクセル以上下にある限り問題ありません。

マウスの変更を追跡し、onbeforeunload イベントをキャプチャするために追加した Javascript を次に示します。

    <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 はまだ試していません。

于 2010-08-27T16:47:46.733 に答える
0

私もこれを探していますが、これまでに見つけたのは、asp.net Web コントロールの代わりにすべてのhtml コントロールを使用するソリューションです。

  <script type="text/javascript">
    $(document).ready(function () {
      $("form").dirty_form();
      $("#btnCancel").dirty_stopper();
    });             
  </script>
于 2010-05-18T14:00:22.610 に答える