49

javascript を使用してフォームの入力の変更を追跡したいと思います。私の意図は(しかしこれに限定されません)

  • 何かが変更された場合にのみ「保存」ボタンを有効にする
  • ユーザーがページを閉じようとしていて、何かが保存されていない場合に警告する

アイデア?

4

15 に答える 15

31

すべての入力要素をループし、onchangeそれぞれにハンドラーを配置します。それが発火したら、フォームが変更されたことを知らせるフラグを設定します。その基本的なバージョンはセットアップが非常に簡単ですが、誰かが入力を「a」から「b」に変更してから「a」に戻した場合に認識できるほどスマートではありません。そのケースをキャッチすることが重要な場合は、まだ可能ですが、もう少し作業が必要です。

jQuery での基本的な例を次に示します。

$("#myForm")
    .on("input", function() {
        // do whatever you need to do when something's changed.
        // perhaps set up an onExit function on the window
        $('#saveButton').show();
    })
;
于 2008-10-11T14:17:47.177 に答える
18

JS のテキスト フォーム要素は.valueプロパティとプロパティを公開するため、次の.defaultValueようなものを簡単に実装できます。

function formChanged(form) {
  for (var i = 0; i < form.elements.length; i++) {
      if(form.elements[i].value != form.elements[i].defaultValue) return(true);
  }
  return(false);
}

チェックボックスとラジオ ボタンについては かどうかを確認element.checked != element.defaultCheckedし、HTML要素については、配列<select />をループして、各オプションが かどうかを確認する必要があります。select.optionsselected == defaultSelected

jQueryのようなフレームワークを使用して、onchange個々のフォーム要素のイベントにハンドラーをアタッチすることを検討してください。formChanged()これらのハンドラーは、コードを呼び出してenabled「保存」ボタンのプロパティを変更したり、ドキュメント本体のイベントのイベント ハンドラーをアタッチ/デタッチしたりできますbeforeunload

于 2008-10-11T14:18:00.590 に答える
6

試す

function isModifiedForm(form){
  var __clone = $(form).clone();
  __clone[0].reset();
  return $(form).serialize() == $(__clone).serialize();
}

その助けを願っています))

于 2013-07-09T12:35:16.253 に答える
2

Ars Technicaでこのような質問に答えましたが、ユーザーがテキストフィールドをぼかしていない場合でも、変更を検出する必要があるように質問が組み立てられました(この場合、変更イベントは発生しません)。私は次のような包括的なスクリプトを思いつきました。

  1. フィールド値が変更された場合に送信ボタンとリセットボタンを有効にします
  2. フォームがリセットされた場合、送信ボタンとリセットボタンを無効にします
  3. フォームデータが変更されて送信されなかった場合、ページを離れるのを中断します
  4. IE 6以降、Firefox 2以降、Safari 3以降をサポートします(おそらくOperaですが、テストしませんでした)

このスクリプトはプロトタイプに依存しますが、別のライブラリに簡単に適合させたり、スタンドアロンにすることができます。

$(document).observe('dom:loaded', function(e) {
    var browser = {
        trident: !!document.all && !window.opera,
        webkit: (!(!!document.all && !window.opera) && !document.doctype) ||
            (!!window.devicePixelRatio && !!window.getMatchedCSSRules)
    };

    // Select form elements that won't bubble up delegated events (eg. onchange)
    var inputs = $('form_id').select('select, input[type="radio"], input[type="checkbox"]');

    $('form_id').observe('submit', function(e) {
        // Don't bother submitting if form not modified
        if(!$('form_id').hasClassName('modified')) {
            e.stop();
            return false;
        }
        $('form_id').addClassName('saving');
    });

    var change = function(e) {
        // Paste event fires before content has been pasted
        if(e && e.type && e.type == 'paste') {
            arguments.callee.defer();
            return false;
        }

        // Check if event actually results in changed data
        if(!e || e.type != 'change') {
            var modified = false;
            $('form_id').getElements().each(function(element) {
                if(element.tagName.match(/^textarea$/i)) {
                    if($F(element) != element.defaultValue) {
                        modified = true;
                    }
                    return;
                } else if(element.tagName.match(/^input$/i)) {
                    if(element.type.match(/^(text|hidden)$/i) && $F(element) != element.defaultValue) {
                        modified = true;
                    } else if(element.type.match(/^(checkbox|radio)$/i) && element.checked != element.defaultChecked) {
                        modified = true;
                    }
                }
            });
            if(!modified) {
                return false;
            }
        }

        // Mark form as modified
        $('form_id').addClassName('modified');

        // Enable submit/reset buttons
        $('reset_button_id').removeAttribute('disabled');
        $('submit_button_id').removeAttribute('disabled');

        // Remove event handlers as they're no longer needed
        if(browser.trident) {
            $('form_id').stopObserving('keyup', change);
            $('form_id').stopObserving('paste', change);
        } else {
            $('form_id').stopObserving('input', change);
        }
        if(browser.webkit) {
            $$('#form_id textarea').invoke('stopObserving', 'keyup', change);
            $$('#form_id textarea').invoke('stopObserving', 'paste', change);
        }
        inputs.invoke('stopObserving', 'change', arguments.callee);
    };

    $('form_id').observe('reset', function(e) {
        // Unset form modified, restart modified check...
        $('reset_button_id').writeAttribute('disabled', true);
        $('submit_button_id').writeAttribute('disabled', true);
        $('form_id').removeClassName('modified');
        startObservers();
    });

    var startObservers = (function(e) {
        if(browser.trident) {
            $('form_id').observe('keyup', change);
            $('form_id').observe('paste', change);
        } else {
            $('form_id').observe('input', change);
        }
        // Webkit apparently doesn't fire oninput in textareas
        if(browser.webkit) {
            $$('#form_id textarea').invoke('observe', 'keyup', change);
            $$('#form_id textarea').invoke('observe', 'paste', change);
        }
        inputs.invoke('observe', 'change', change);
        return arguments.callee;
    })();

    window.onbeforeunload = function(e) {
        if($('form_id').hasClassName('modified') && !$('form_id').hasClassName('saving')) {
            return 'You have unsaved content, would you really like to leave the page? All your changes will be lost.';
        }
    };

});
于 2008-10-11T17:27:37.730 に答える
2

Web アプリ フレームワーク (rails、ASP.NET、Cake、symfony) を使用している場合は、ajax 検証用のパッケージが必要です。

http://webtecker.com/2008/03/17/list-of-ajax-form-validators/

フォームを閉じようとしているユーザーに警告する onbeforeunload() のラッパー:

http://pragmatig.wordpress.com/2008/03/03/protecting-userdata-from-beeing-lost-with-jquery/保存されて いない変更の検出

于 2008-10-11T14:19:47.873 に答える
1

ページが読み込まれるときに各フィールドの値を変数に格納し、ユーザーがページを読み込むときにそれらの値を比較します。違いが検出された場合は、何を保存すればよいかがわかり、さらに良いことに、ユーザーが終了した場合にどのデータが保存されないかを具体的にユーザーに伝えることができます。

// this example uses the prototype library
// also, it's not very efficient, I just threw it together
var valuesAtLoad = [];
var valuesOnCheck = [];
var isDirty = false;
var names = [];
Event.observe(window, 'load', function() {
    $$('.field').each(function(i) {
        valuesAtLoad.push($F(i));
    });
});

var checkValues = function() {
    var changes = [];
    valuesOnCheck = [];
    $$('.field').each(function(i) {
        valuesOnCheck.push($F(i));
    });

    for(var i = 0; i <= valuesOnCheck.length - 1; i++ ) {
        var source = valuesOnCheck[i];
        var compare = valuesAtLoad[i];
        if( source !== compare ) {
            changes.push($$('.field')[i]);
        }
    }

    return changes.length > 0 ? changes : [];
};

setInterval(function() { names = checkValues().pluck('id'); isDirty = names.length > 0; }, 100);

// notify the user when they exit
Event.observe(window, 'beforeunload', function(e) {
     e.returnValue = isDirty ? "you have changed the following fields: \r\n" + names + "\r\n these changes will be lost if you exit. Are you sure you want to continue?" : true;
});
于 2008-10-11T18:02:12.543 に答える
1

私はdirtyforms.jsを使用しました。私にとってはうまくいきます。

http://mal.co.nz/code/jquery-dirty-forms/

于 2013-02-25T19:58:55.567 に答える
1

閉じる前にユーザーに警告するには、unbeforeunload を使用します。

window.onbeforeunload = function() {
   return "You are about to lose your form data.";
};
于 2008-10-11T14:22:47.727 に答える
0

また、フォームプラグインのjQueryトラック変更で作成したこのjQueryプラグインを確認することもできます。

こちらのデモをご覧になり、こちらからJSをダウンロードしてください

于 2008-12-31T06:04:54.430 に答える
0

Dylan Beattie の提案の完全な実装は次のとおりです。

「保存されていないデータ」保護のためのクライアント/JS フレームワーク?

クライアント側で動的に入力する場合を除き、フォームが変更されたかどうかを判断するために初期値を保存する必要はありません (ただし、その場合でもdefault、フォーム要素にプロパティを設定することはできます)。

于 2008-10-11T18:28:44.720 に答える
0

クロスブラウザテストを行いました。

Chrome と Safari では、これは便利です。

<form onchange="validate()">
...
</form>

Firefox + Chrome/Safari の場合は、次のようにします。

<form onkeydown="validate()">
    ...
    <input type="checkbox" onchange="validate()">
</form>

チェックボックスやラジオボタンなどの項目には、独自の onchange イベント リスナーが必要です。

于 2015-04-29T14:06:17.973 に答える
0

各フォーム入力/選択/テキストエリアの onchange イベントにイベント ハンドラーをアタッチします。「保存」ボタンを有効にする必要があるかどうかを示す変数を設定します。ダーティ フォームもチェックする onunload ハンドラを作成し、フォームが送信されたら変数をリセットします。

window.onunload = checkUnsavedPage;
var isDirty = false;
var formElements = //すべてのフォーム要素への参照を取得します
for(var i = 0; len = formElements.length; i++) {
    // 各要素に onchange イベントを追加して formChanged() を呼び出します
}

関数 formChanged(イベント) {
    isDirty = false;
    document.getElementById("savebtn").disabled = "";
}

関数 checkUnsavedPage() {
    もし (汚れている) {
        var isSure = confirm("よろしいですか?");  
        if (!isSure) {
            event.preventDefault();
        }
    }
}
于 2008-10-11T14:21:53.983 に答える