Avisar o usuário antes de sair da página da Web com alterações não salvas


341

Eu tenho algumas páginas com formulários no meu aplicativo.

Como posso proteger o formulário de tal maneira que, se alguém navegar ou fechar a guia do navegador, será solicitado que você confirme que realmente deseja deixar o formulário com dados não salvos?



3
Esta pergunta aqui deve ter a resposta que você
procura


Respostas:


556

Resposta curta e errada:

Você pode fazer isso manipulando o beforeunloadevento e retornando uma sequência não nula :

window.addEventListener("beforeunload", function (e) {
    var confirmationMessage = 'It looks like you have been editing something. '
                            + 'If you leave before saving, your changes will be lost.';

    (e || window.event).returnValue = confirmationMessage; //Gecko + IE
    return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});

O problema dessa abordagem é que o envio de um formulário também está disparando o evento descarregar . Isso é corrigido facilmente adicionando o sinalizador a que você está enviando um formulário:

var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

Em seguida, ligue para o setter ao enviar:

<form method="post" onsubmit="setFormSubmitting()">     
    <input type="submit" />
</form>

Mas continue a ler ...

Resposta longa e correta:

Você também não deseja mostrar esta mensagem quando o usuário não alterou nada nos seus formulários . Uma solução é usar o beforeunloadevento em combinação com um sinalizador "sujo", que somente aciona o prompt se for realmente relevante.

var isDirty = function() { return false; }

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting || !isDirty()) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

Agora, para implementar o isDirtymétodo, existem várias abordagens.

Você pode usar jQuery e serialização de formulários , mas essa abordagem tem algumas falhas. Primeiro, você precisa alterar o código para funcionar de qualquer forma (o $("form").each()que funcionará), mas o maior problema é que o jQuery serialize()funcionará apenas em elementos nomeados e não desativados; portanto, alterar qualquer elemento desativado ou não nomeado não acionará o sinalizador sujo. Existem soluções alternativas para isso , como fazer controles somente leitura em vez de habilitar, serializar e desabilitar os controles novamente.

Então os eventos parecem o caminho a percorrer. Você pode tentar ouvir as teclas pressionadas . Este evento tem alguns problemas:

  • Não será acionado em caixas de seleção, botões de opção ou outros elementos que estão sendo alterados através da entrada do mouse.
  • Irá acionar pressionamentos de tecla irrelevantes como a Ctrltecla.
  • Não acionará valores definidos pelo código JavaScript.
  • Não será acionado ao recortar ou colar texto nos menus de contexto.
  • Não funcionará para entradas virtuais, como seletores de datas ou embelezadores de caixa de seleção / botão de rádio, que economizam seu valor em uma entrada oculta por meio de JavaScript.

O changeevento também não dispara nos valores definidos no código JavaScript , também não funciona para entradas virtuais.

Vinculando o inputevento para todos os inputs (e textareas e selects) na sua página não irá funcionar em navegadores mais antigos e, como todas as soluções de tratamento de evento mencionado acima, não suporta desfazer. Quando um usuário altera uma caixa de texto e a desfaz, ou marca e desmarca uma caixa de seleção, o formulário ainda é considerado sujo.

E quando você deseja implementar mais comportamentos, como ignorar certos elementos, terá ainda mais trabalho a fazer.

Não reinvente a roda:

Portanto, antes de pensar em implementar essas soluções e todas as soluções necessárias, perceba que você está reinventando a roda e está propenso a encontrar problemas que outras pessoas já resolveram para você.

Se seu aplicativo já usa jQuery, você também pode usar código testado e mantido em vez de criar o seu próprio e usar uma biblioteca de terceiros para tudo isso. jQuery tem certeza? plugin funciona muito bem, veja sua página de demonstração . É simples assim:

<script src="jquery.are-you-sure.js"></script>

<script>
  $(function() {
    $('#myForm').areYouSure(
      {
        message: 'It looks like you have been editing something. '
               + 'If you leave before saving, your changes will be lost.'
      }
    );
  });

</script>

Mensagens personalizadas não suportadas em qualquer lugar

Observe que o Firefox 4 não suporta mensagens personalizadas nesta caixa de diálogo. A partir de abril de 2016, o Chrome 51 está sendo implementado, no qual as mensagens personalizadas também estão sendo removidas .

Algumas alternativas existem em outras partes deste site, mas acho que uma caixa de diálogo como essa é clara o suficiente:

Deseja sair deste site?

As alterações feitas podem não ser salvas.

Leave Stay


6
Observe que o uso de strings personalizadas não funciona mais no Chrome; chromestatus.com/feature/5349061406228480
amann

5
Sim, isso está descrito na última seção da minha resposta.
CodeCaster

2
@ Chris, porque o Angular está manipulando o DOM para alterar a página, sem sair do documento atual.
CodeCaster 4/17/17

15
Esteja avisado de que o jQuery areYouSure foi abandonado desde 2014 (57 questões abertas no Github ), está cheio de bugs da minha experiência, pode parecer que funciona no começo, mas depois de alguns testes rápidos, percebi que nem sempre funciona. Não recomendaria isso de forma alguma #
Mark Mark

4
@JacopoStanchi Infelizmente, não encontrei nenhum. Quero dizer, eu parecia bastante - mas isso foi em 10 de janeiro, então alguém pode ter escrito alguma coisa, mas duvido. Sua melhor aposta é implementá-lo você mesmo - não é o que você quer ouvir, mas sinto muito. (Mas pelo menos você não terá nenhuma surpresa como eu fiz usando jQuery AreYouSure.) Além disso, quem sabe talvez você pode até mesmo torná-lo open source e sua implementação seria compartilhado com os outros;)
Mark

75

Confira o evento JavaScript onbeforeunload . É um JavaScript não padrão introduzido pela Microsoft, no entanto, funciona na maioria dos navegadores e sua documentação onbeforeunload tem mais informações e exemplos.


3
Eu acho que agora se tornou padrão. >> O evento foi originalmente apresentado pela Microsoft no Internet Explorer 4 e padronizado na especificação HTML5.
vee

34

via jquery

$('#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 warning box, else don't show it.
});

Você pode usar a função Serializar formulário do Google JQuery, isso irá coletar todas as entradas do formulário e salvá-lo na matriz. Eu acho que essa explicação é suficiente :)


6
não use #form como forma id porque a janela irá criar e objeto nomeado forma :)
mdikici

11
Verifique aqui se não está funcionando para você: stackoverflow.com/questions/7080269/…
Leniel Maccaferri

16

Solução universal que não requer configuração que detecte automaticamente todas as modificações de entrada, incluindo elementos editáveis ​​por conteúdo:

"use strict";
(() => {
const modified_inputs = new Set;
const defaultValue = "defaultValue";
// store default values
addEventListener("beforeinput", (evt) => {
    const target = evt.target;
    if (!(defaultValue in target || defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ("" + (target.value || target.textContent)).trim();
    }
});
// detect input modifications
addEventListener("input", (evt) => {
    const target = evt.target;
    let original;
    if (defaultValue in target) {
        original = target[defaultValue];
    } else {
        original = target.dataset[defaultValue];
    }
    if (original !== ("" + (target.value || target.textContent)).trim()) {
        if (!modified_inputs.has(target)) {
            modified_inputs.add(target);
        }
    } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
    }
});
// clear modified inputs upon form submission
addEventListener("submit", () => {
    modified_inputs.clear();
    // to prevent the warning from happening, it is advisable
    // that you clear your form controls back to their default
    // state after submission
});
// warn before closing if any inputs are modified
addEventListener("beforeunload", (evt) => {
    if (modified_inputs.size) {
        const unsaved_changes_warning = "Changes you made may not be saved.";
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
    }
});
})();

11
Feijão fresco. Apenas copie e cole esse código na sua página de teste, faça uma alteração e clique em Atualizar. Ele exibirá um alerta nativo do navegador, avisando que você possui alterações não salvas.
TheLegendaryCopyCoder

11
Isso funcionou para mim no Chrome 71.0.3578.98 (Versão oficial) (64-bit)
JacobRossDev

2
Isso funciona muito bem, mas se você estiver usando isso com um formulário para envio, será necessário limpar primeiro as entradas de modificação modificadas antes de receber um alerta de confirmação de alterações. Adicionei um ouvinte de evento ao meu formulário para solicitar o envio e apenas executei a função set clear, para que as entradas_de_ modificação sejam limpas quando o descarregador de eventos unload for executado e permita que a postagem continue.
stepquick

11
Legal, na verdade, copie e cole. obrigado por economizar meu tempo. Trabalhe para mim no Firfox 75.0
Connectify_user

11
Amo esse trecho
Rawburner 09/06

10

Construído sobre a excelente idéia de Wasim A. de usar serialização. O problema era que o aviso também era mostrado quando o formulário estava sendo enviado. Isso foi corrigido aqui.

var isSubmitting = false

$(document).ready(function () {
    $('form').submit(function(){
        isSubmitting = true
    })

    $('form').data('initial-state', $('form').serialize());

    $(window).on('beforeunload', function() {
        if (!isSubmitting && $('form').serialize() != $('form').data('initial-state')){
            return 'You have unsaved changes which will not be saved.'
        }
    });
})

Foi testado no Chrome e IE 11.


Wasim A e Eerik Sven Puudist - Obrigado, usei id para formulário e id para meu botão salvar, pois todos os meus botões eram do tipo submit <form action = "" id = "marksform" method = "POST"> <td> <input type = "submit" name = "submit_button" id = "save" value = "Save"> </td> <td> <input type = "submit" name = "submit_button" value = "Next"> </td> e poucos mais todos os tipos de envio Portanto substituídos .Submit (por clique específico $ ('# save'). click (function () {isSubmitting = true}) Use '#marksform' em vez de 'form'
Jayanta

7

Com base nas respostas anteriores e reunidas de vários lugares no estouro de pilha, eis a solução que eu criei que lida com o caso quando você realmente deseja enviar suas alterações:

window.thisPage = window.thisPage || {};
window.thisPage.isDirty = false;

window.thisPage.closeEditorWarning = function (event) {
    if (window.thisPage.isDirty)
        return 'It looks like you have been editing something' +
               ' - if you leave before saving, then your changes will be lost.'
    else
        return undefined;
};

$("form").on('keyup', 'textarea', // You can use input[type=text] here as well.
             function () { 
                 window.thisPage.isDirty = true; 
             });

$("form").submit(function () {
    QC.thisPage.isDirty = false;
});
window.onbeforeunload = window.thisPage.closeEditorWarning;

Vale ressaltar que o IE11 parece exigir que a closeEditorWarningfunção retorne undefinedpara não mostrar um alerta.


Esta solução não verifica se algum valor foi alterado em relação ao seu estado original, invalidando o caso de o usuário inserir texto e excluir o texto inserido antes de tentar sair.
Brett Weber

Bom ponto, @BrettWeber. Você pode modificar closeEditorWarning nesse caso e ter "if (window.thisPage.isDirty && uiHasChanged ())", em que uiHasChanged é uma função que conhece o estado original do servidor e verifica todas as diferenças, mas esta solução foi um caso em que eu particularmente não queria fazer todo esse trabalho extra, e isso só tem falsos positivos quando pressionamentos de tecla reais foram feitos nas áreas de texto, o que eu senti como um compromisso razoável. :)
Jonathan

Não deveria QC.thisPage.isDirty = false;ser window.thisPage.isDirty = false;? Dessa forma, ele verificará se você está enviando o formulário e não mostra um aviso. Parecia funcionar para os meus testes. Além disso, a maioria dos formulários possui um inpute não um textarea. Eu usei o seguinte, que funciona bastante bem: #$("form").on('keyup', 'textarea,input,select', function () {
2576 Mike Mike

7

A seguinte linha funcionou para mim.

window.onbeforeunload = s => modified ? "" : null;

Basta definir modifiedcomo verdadeiro ou falso, dependendo do estado do seu aplicativo.


2
Algumas sugestões: Retorne uma mensagem personalizada em vez de uma string vazia, pois alguns navegadores a exibirão (por exemplo, Edge) e retorne em undefinedvez de nullo IE imprimir 'null' se modifiedfor falso.
Kevin Lee

11
e os dispositivos móveis? meu entendimento é que os dispositivos IOS não respeitam onbeforeunload.
Jaybro # 10/18

4

O código a seguir funciona muito bem. Você precisa acessar as alterações de entrada dos elementos do formulário por meio do atributo id:

var somethingChanged=false;
            $('#managerForm input').change(function() { 
                somethingChanged = true; 
           }); 
            $(window).bind('beforeunload', function(e){
                if(somethingChanged)
                    return "You made some changes and it's not saved?";
                else 
                    e=null; // i.e; if form state change show warning box, else don't show it.
            });
        });

3
var unsaved = false;
$(":input").change(function () {         
    unsaved = true;
});

function unloadPage() {         
    if (unsaved) {             
        alert("You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?");
    }
} 
window.onbeforeunload = unloadPage;

Eu o inseri em um arquivo separado e o incluí com <script src = "warnOnChange.js"> </script>, mas nada acontece quando eu modifico um campo de texto e, em seguida, executo um comando de cabeçalho.
Fabrizio Bartolomucci

2

Você pode usar serialize () para criar uma sequência de texto codificada em URL serializando os valores do formulário e verificar se o formulário foi alterado antes da transferência

$(document).ready(function(){
    var form = $('#some-form'),
        original = form.serialize()

    form.submit(function(){
        window.onbeforeunload = null
    })

    window.onbeforeunload = function(){
        if (form.serialize() != original)
            return 'Are you sure you want to leave?'
    }
})

Consulte este link https://coderwall.com/p/gny70a/alert-when-leaving-page-with-unsaved-form Escrito por Vladimir Sidorenko


11
Funcionou, mas, conforme respondido pelo código caster, existem algumas falhas com esse método, consulte esta explicação stackoverflow.com/a/7317311/10555981
Pradeep

Já existem algumas respostas usando serialize(), e de fato, ele tem suas desvantagens.
CodeCaster

Essa deve ser a resposta correta, muito simples de usar e funciona conforme o esperado.
Jodyshop #

1

Adicionando à idéia do @codecaster, você pode adicioná-lo a todas as páginas com um formulário (no meu caso, eu o uso de maneira global, para que apenas nos formulários o aviso) altere sua função para

if ( formSubmitting || document.getElementsByTagName('form').length == 0) 

Também envie formulários, incluindo links de login e botões de cancelamento, para que quando a pessoa pressionar cancelar ou enviar o formulário não acionar o aviso também em todas as páginas com um formulário ...

<a class="btn btn-danger btn-md" href="back/url" onclick="setFormSubmitting()">Cancel</a>

1

Você pode verificar uma explicação detalhada aqui: http://techinvestigations.redexp.in/comparison-of-form-values-on-load-and-before-close/ comparação-de-forma-valores-em-carga-e -before-close

O código principal:

function formCompare(defaultValues, valuesOnClose) {

    // Create arrays of property names
    var aPropsFormLoad = Object.keys(defaultValues);
    var aPropsFormClose = Object.keys(valuesOnClose);

    // If number of properties is different,
    // objects are not equivalent
    if (aPropsFormLoad.length != aPropsFormClose.length) {
        return false;
    }

    for (var i = 0; i < aPropsFormLoad.length; i++) {
        var propName = aPropsFormLoad[i];

        // If values of same property are not equal,
        // objects are not equivalent
        if (defaultValues[aPropsFormLoad]+"" !== valuesOnClose[aPropsFormLoad]+"") {
            return false;
        }
    }

    // If we made it this far, objects
    // are considered equivalent
    return true;

}

//add polyfill for older browsers, as explained on the link above

//use the block below on load
    for(i=0; i < document.forms[0].elements.length; i++){
    console.log("The field name is: " + document.forms[0].elements[i].name +
        " and it’s value is: " + document.forms[0].elements[i].value );
    aPropsFormLoad[i] = document.forms[0].elements[i].value;
    }

//create a similar array on window unload event.

//and call the utility function
    if (!formCompare(aPropsOnLoad, aPropsOnClose))
    {
    //perform action: 
    //ask user for confirmation or
    //display message about changes made
    }

1

Resposta curta:

let pageModified = true

window.addEventListener("beforeunload", 
  () => pageModified ? 'Close page without saving data?' : null
)

1

A solução de Eerik Sven Puudist ...

var isSubmitting = false;

$(document).ready(function () {
    $('form').submit(function(){
        isSubmitting = true
    })

    $('form').data('initial-state', $('form').serialize());

    $(window).on('beforeunload', function() {
        if (!isSubmitting && $('form').serialize() != $('form').data('initial-state')){
            return 'You have unsaved changes which will not be saved.'
        }
    });
})

... fez o trabalho espontaneamente para mim em um cenário complexo orientado a objetos, sem as alterações necessárias.

A única alteração que apliquei foi me referir ao formulário concreto (apenas um formulário por arquivo) chamado "formForm" ('form' -> '#formForm'):

<form ... id="formForm" name="formForm" ...>

Especialmente bem feito é o fato de que o botão enviar está sendo "deixado em paz".

Além disso, ele funciona para mim também com a versão mais recente do Firefox (a partir de 7 de fevereiro de 2019).


1

Testado a solução universal de Eli Grey, só funcionou depois que simplifiquei o código para

  'use strict';
  (() => {
    const modified_inputs = new Set();
    const defaultValue = 'defaultValue';
    // store default values
    addEventListener('beforeinput', evt => {
      const target = evt.target;
      if (!(defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
      }
    });

    // detect input modifications
    addEventListener('input', evt => {
      const target = evt.target;
      let original = target.dataset[defaultValue];

      let current = ('' + (target.value || target.textContent)).trim();

      if (original !== current) {
        if (!modified_inputs.has(target)) {
          modified_inputs.add(target);
        }
      } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
      }
    });

    addEventListener(
      'saved',
      function(e) {
        modified_inputs.clear()
      },
      false
    );

    addEventListener('beforeunload', evt => {
      if (modified_inputs.size) {
        const unsaved_changes_warning = 'Changes you made may not be saved.';
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
      }
    });

  })();

As modificações nele são excluídas do uso target[defaultValue]e uso exclusivotarget.dataset[defaultValue] para armazenar o valor padrão real.

E eu adicionei um ouvinte de evento 'salvo', onde o evento 'salvo' será acionado por você mesmo em sua ação de salvamento bem-sucedida.

Mas essa solução "universal" funciona apenas em navegadores, não na visualização da web do aplicativo, por exemplo, nos navegadores.

Para fazê-lo funcionar também nos navegadores wechat (parcialmente), outras melhorias:

  'use strict';
  (() => {
    const modified_inputs = new Set();
    const defaultValue = 'defaultValue';
    // store default values
    addEventListener('beforeinput', evt => {
      const target = evt.target;
      if (!(defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
      }
    });

    // detect input modifications
    addEventListener('input', evt => {
      const target = evt.target;
      let original = target.dataset[defaultValue];

      let current = ('' + (target.value || target.textContent)).trim();

      if (original !== current) {
        if (!modified_inputs.has(target)) {
          modified_inputs.add(target);
        }
      } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
      }

      if(modified_inputs.size){
        const event = new Event('needSave')
        window.dispatchEvent(event);
      }
    });

    addEventListener(
      'saved',
      function(e) {
        modified_inputs.clear()
      },
      false
    );

    addEventListener('beforeunload', evt => {
      if (modified_inputs.size) {
        const unsaved_changes_warning = 'Changes you made may not be saved.';
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
      }
    });

    const ua = navigator.userAgent.toLowerCase();

    if(/MicroMessenger/i.test(ua)) {
      let pushed = false

      addEventListener('needSave', evt => {
        if(!pushed) {
          pushHistory();

          window.addEventListener("popstate", function(e) {
            if(modified_inputs.size) {
              var cfi = confirm('确定要离开当前页面嘛?' + JSON.stringify(e));
              if (cfi) {
                modified_inputs.clear()
                history.go(-1)
              }else{
                e.preventDefault();
                e.stopPropagation();
              }
            }
          }, false);
        }

        pushed = true
      });
    }

    function pushHistory() {
      var state = {
        title: document.title,
        url: "#flag"
      };
      window.history.pushState(state, document.title, "#flag");
    }
  })();

0

Fiz isso de maneira diferente, compartilhando aqui para que alguém possa obter ajuda, testado apenas com o Chrome.

Eu queria avisar o usuário antes de fechar a guia apenas se houver algumas alterações.

<input type="text" name="field" value="" class="onchange" />

var ischanged = false;

$('.onchange').change(function () {
    ischanged = true;
});

window.onbeforeunload = function (e) {
    if (ischanged) {
        return "Make sure to save all changes.";
    }        
};

Funciona bem, mas tenho outro problema. Quando envio o formulário, recebo o aviso indesejado, vi muitas soluções alternativas, isso ocorre porque onbeforeunload dispara antes do onsubmit, é por isso que não podemos lidar com isso no evento onsubmit como onbeforeunload = null, mas O evento onclick do botão enviar é acionado antes desses dois eventos, então atualizei o código

var isChanged = false;
var isSubmit = false;

window.onbeforeunload = function (e) {
    if (isChanged && (!isSubmit)) {
        return "Make sure to save all changes.";
    }        
};

$('#submitbutton').click(function () {
    isSubmit = true;
});

$('.onchange').change(function () {
    isChanged = true;
});

-5

Primeiro de tudo, a maioria dos navegadores tem essa função por padrão. E por que você precisa disso? Por que não manter o formulário sincronizado? Quero dizer, salve-o em qualquer alteração sem esperar nenhum envio do usuário. Como os Contatos do Google fazem. Obviamente, se apenas todos os campos no formulário forem obrigatórios. Os usuários não gostam de quando forçam a preencher algo sem a oportunidade de ir embora para pensar se precisam. :)


você está certo, mas meus formulários são gerados dinamicamente e os campos não estão sob meu controle, portanto, para mim não é possível rastrear todos os campos e enviar solicitações através do ajax, se você tiver algo em mente, compartilhe comigo.
Khan

Ok, pode não ser necessário para seus propósitos, mas ainda pode ser implementado. Se os elementos do formulário estiverem na tela, você poderá anexar seus próprios manipuladores de eventos e obter os dados desejados. Em seguida, use o AJAX para salvar os dados onde quiser. Mesmo que os formulários tenham gerado IDs ou nomes de classe aleatoriamente, você pode usar o XPaths se puder antecipar a estrutura do formulário. É XML / HTML, certo? Assim, você pode até ter um JAD com as pessoas responsáveis ​​pelo formulário gerado dinamicamente e conversar sobre como o XSTL poderia beneficiar os dois neste projeto. Apenas um pensamento ...
SimonDever

11
save it on any change without waiting any submitting from userVocê nem sempre quer fazer isso. Às vezes, o usuário deseja fazer muitas alterações, revisar e confirmar que deseja salvá-lo.
BadHorsie

11
Não sugeri enviar o formulário. Os dados podem ser salvos no localStorage, em algum cache ou até mesmo enviados com algum sinalizador de rascunho. Existem muitos métodos para esse comportamento. É muito melhor do que alertar o usuário sobre o fato de ele não ter concluído o formulário e, se ele não fechar e fechar a janela, ele precisará preenchê-lo novamente na próxima vez. "Vamos lá, cara, não seja preguiçoso, seu trem / ônibus / avião / etc. Não importa tão bem quanto não nos importamos que você tenha esquecido um carregador do seu laptop, basta preencher este maldito formulário!"
YuS
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.