19 Stimmen

Bestätigen Sie, dass Sie die Seite verlassen, wenn Sie ein Formular mit jQuery bearbeiten

Ich kodiere ein Formular und brauche eine Funktion, wie sie Stackoverflow hat: "Sie haben begonnen, einen Beitrag zu schreiben oder zu bearbeiten.".

Ich habe den Code von Stackoverflow durchgesehen, um zu sehen, wie sie es tun, aber ich bekomme es überhaupt nicht auf mein einfaches Formular anwenden. Dies ist, was sie auf question.js haben:

function initNavPrevention(b) {
    if (b.which == "undefined") {
        return
    }
    var a = $("#wmd-input");
    a.unbind("keypress", initNavPrevention);
    setConfirmUnload("You have started writing or editing a post.", a)
}

Eine der Funktionen löst dies aus (ich weiß nicht, was c ist):

if (c) {
    e.keypress(initNavPrevention)
}

Und schließlich haben sie setConfirmUnload(null); um sie zu deaktivieren, nehme ich an.

Mein Fall ist einfach. Ich habe eine Seite, auf der ich eine <form /> über AJAX und ich möchte verhindern, wenn dieses Formular geladen wird, um die Seite zu verlassen, ohne auf die Schaltfläche SUBMIT zu klicken oder wenn der Benutzer auf CANCEL klickt das Formular deaktiviert ist und die Prävention wird nicht Popup.

Kann mir jemand sagen, wie ich diesen Code in meine Website einbauen kann?

Dies ist meine AJAX-Funktion zum Laden des Formulars:

$("#projects_historics_edit_part_1").click(function(){
    $("#ajax-loader").fadeIn('normal');

    $.ajax({
        url: BASE_URL + 'projects/ajax/get_historics_edit_part_1/' + PROJECT_ID,
        type: "POST",
        success: function(data) {
            $("div#projects_historics_part_1").html(data);

            $("#client").autocomplete(client_autcomplete_options);

            var inicofin = $("#initdate, #findate").datepicker(initdate_datepicker_options);
        }
    });

    $("#ajax-loader").fadeOut("normal");

    return false;    
});

Vielen Dank im Voraus!

32voto

betamax Punkte 12531

Sie können dies tun mit window.onbeforeunload wie diese:

window.onbeforeunload = function() {
    return 'Are you sure you want to navigate away from this page?';
};

In Ihrem Code würden Sie das also innerhalb der success Rückruf Ihrer $.ajax anrufen.

Um die Bestätigung aufzuheben, können Sie wie folgt vorgehen:

window.onbeforeunload = null;

Siehe auch diese Antwort: Wie kann ich den OnBeforeUnload-Dialog überschreiben und durch meinen eigenen ersetzen?

15voto

Wasim A. Punkte 9161

In JQuery geht das so

$('#form').data('serialize',$('#form').serialize());
  // On load save form current state

$(window).bind('beforeunload', function(e){
    if($('#form').serialize()!=$('#form').data('serialize'))return true;
    else e=null;
    // i.e; if form state change show box not.
});

Sie können Google JQuery Form Serialize Funktion, wird dies alle Eingaben zu sammeln und speichern Sie sie in Array. Ich denke, diese Erklärung ist genug :)

3voto

Sam Watkins Punkte 7162

Auf der Grundlage von Wasims hervorragender Antwort habe ich eine allgemeine Funktion für diese Aufgabe entwickelt:

var confirm_nav_ignore = [];
function confirm_nav() {
    function save_form_state($form) {
        var old_state = $form.serialize();
        $form.data('old_state', old_state);
    }

    // On load, save form current state
    $('form').each(function() {
        save_form_state($(this));
    });

    // On submit, save form current state
    $('form').submit(function() {
        save_form_state($(this));
    });

    // strip fields that we should ignore
    function strip(form_data) {
        for (var i=0; i<confirm_nav_ignore.length; i++) {
            var field = confirm_nav_ignore[i];
            form_data = form_data.replace(new RegExp("\\b"+field+"=[^&]*"), '');
        }   
        return form_data;
    }

    // Before unload, confirm navigation if any field has been edited
    $(window).on('beforeunload', function(e) {
        var rv;
        $('form').each(function() {
            var $form = $(this);
            var old_state = strip($form.data('old_state'));
            var new_state = strip($form.serialize());
            if (new_state != old_state) {
                rv = '';
            }   
        }); 
        return rv;
    }); 
}

// I call it at the end of the on-load handler:
$(function() {
    confirm_nav();
});

Änderungen:

  1. Ermöglicht das Absenden eines Formulars ohne Bestätigung.
  2. Funktioniert mit mehreren Formularen, mit $('form').each(...)
  3. Hängt nicht davon ab, dass das Formular id="form" hat
  4. Gibt '' als benutzerdefinierte Bestätigungsmeldung zurück, anstelle von true, das in Chrome "true" anzeigt.
  5. Für schwierige Seiten kann es angewiesen werden, bestimmte Formularfelder zu ignorieren.
  6. Führen Sie es am Ende des On-Load-Handlers aus... scheint eine gute Idee zu sein.
  7. Sie ist so allgemein, dass wir sie auf jeder Seite einer Website verwenden können.

Es sieht vielleicht übertrieben aus, aber genau das musste ich tun, damit es in einer echten Webanwendung richtig funktioniert.

Vielen Dank an Wasim, für die großartige Idee, JQuery $(form).serialize() zu verwenden.

0voto

Danil Pyatnitsev Punkte 2032

Basierend auf der Antwort von Wasim A.. Der Code sieht gut aus, aber wenn ich auf die Schaltfläche "Senden" klicke, erhalte ich auch eine Benachrichtigung. Ich denke, dies ist besser:

$(document).ready(function() {
    let form = $('#form');
    form.data('serialize', form.serialize());

    // if submit clicked - pass user to save form
    form.find('submit').on('click', function () {
        $(window).off('beforeunload');
    });
});

  // On load save form current state

$(window).bind('beforeunload', function(e){
    let form = $('#form');
    if(form.serialize() !== form.data('serialize')) {
      return true;
    } else {
    // i.e; if form state change show box not.
      e=null;
    }
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

0voto

Gassan Punkte 71

Eine kleine Optimierung der hervorragenden Antwort von Sam:

var confirm_nav_ignore = [];
function confirm_nav() {
    var $forms = $('form'); // if you need it add .filter('#your_form_id');

    function save_form_state() {
        var $form = $(this),
            old_state = $form.serialize();
        $form.data('old_state', old_state);
    }

    $forms
        // On load, save form current state
        .each(save_form_state)
        // On submit, save form current state
        .submit(save_form_state)
    ;

    // strip fields that we should ignore
    function strip(form_data) {
        for (var i = 0; i < confirm_nav_ignore.length; i++) {
            var field = confirm_nav_ignore[i];
            form_data = form_data.replace(new RegExp("\\b" + field + "=[^&]*"), '');
        }

        return form_data;
    }

    // Before unload, confirm navigation if any field has been edited
    $(window).on('beforeunload', function(e) {
        var rv = undefined;

        $forms.each(function() {
            var $form = $(this);
            var old_state = strip($form.data('old_state'));
            var new_state = strip($form.serialize());
            if (new_state !== old_state) {
                e.preventDefault();
                rv = '';
            }
        });

        return rv;
    });
}
// I call it at the end of the on-load handler:
$(confirm_nav);

getestet mit Chrome, Firefox und Safari

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X