Avisar al usuario antes de abandonar la página web con cambios no guardados


341

Tengo algunas páginas con formularios en mi solicitud.

¿Cómo puedo asegurar el formulario de tal manera que si alguien se aleja o cierra la pestaña del navegador, se les debe solicitar que confirmen que realmente quieren dejar el formulario con datos no guardados?



3
Esta pregunta aquí debería tener la respuesta que
busca


Respuestas:


556

Respuesta corta e incorrecta:

Puede hacer esto manejando el beforeunloadevento y devolviendo una cadena no 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.
});

El problema con este enfoque es que enviar un formulario también está activando el evento de descarga . Esto se soluciona fácilmente agregando una marca que está enviando un formulario:

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.
    });
};

Luego llamando al setter al enviar:

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

Pero sigue leyendo ...

Respuesta larga y correcta:

Tampoco desea mostrar este mensaje cuando el usuario no ha cambiado nada en sus formularios . Una solución es usar el beforeunloadevento en combinación con una bandera "sucia", que solo activa el aviso si es 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.
    });
};

Ahora para implementar el isDirtymétodo, hay varios enfoques.

Puede usar jQuery y la serialización de formularios , pero este enfoque tiene algunos defectos. Primero, tiene que modificar el código para que funcione en cualquier forma ( $("form").each()lo hará), pero el mayor problema es que jQuery serialize()solo funcionará en elementos con nombre y sin discapacidad, por lo que cambiar cualquier elemento con o sin nombre no activará el indicador sucio. Hay soluciones alternativas para eso , como hacer que los controles sean de solo lectura en lugar de habilitar, serializar y luego deshabilitar los controles nuevamente.

Entonces los eventos parecen el camino a seguir. Puedes intentar escuchar las pulsaciones de teclas . Este evento tiene algunos problemas:

  • No se activará en casillas de verificación, botones de radio u otros elementos que se están alterando a través de la entrada del mouse.
  • Se activará para pulsaciones de teclas irrelevantes como la Ctrltecla.
  • No se activará en valores establecidos a través del código JavaScript.
  • No se activará al cortar o pegar texto a través de menús contextuales.
  • No funcionará para entradas virtuales como fechadores o embellecedores de casillas de verificación / botones de radio que guardan su valor en una entrada oculta a través de JavaScript.

El changeevento también no se activa en los valores establecidos de código JavaScript , por lo que también no funcionará para entradas virtuales.

Vincular el inputevento a todos los inputs (y textareas y selects) en su página no funcionará en navegadores antiguos y, como todas las soluciones de manejo de eventos mencionadas anteriormente, no admite deshacer. Cuando un usuario cambia un cuadro de texto y luego lo deshace, o marca y desmarca una casilla de verificación, el formulario aún se considera sucio.

Y cuando desee implementar más comportamiento, como ignorar ciertos elementos, tendrá aún más trabajo por hacer.

No reinventes la rueda:

Entonces, antes de pensar en implementar esas soluciones y todas las soluciones alternativas necesarias, tenga en cuenta que está reinventando la rueda y que es probable que tenga problemas que otros ya han resuelto para usted.

Si su aplicación ya usa jQuery, también puede usar código probado y mantenido en lugar de crear el suyo propio, y usar una biblioteca de terceros para todo esto. jQuery's ¿Estás seguro? El complemento funciona muy bien, vea su página de demostración . Es tan simple como esto:

<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>

Mensajes personalizados no admitidos en todas partes

Tenga en cuenta que Firefox 4 no admite mensajes personalizados en este cuadro de diálogo. A partir de abril de 2016, Chrome 51 se está implementando en el que también se eliminan los mensajes personalizados .

Existen otras alternativas en otras partes de este sitio, pero creo que un diálogo como este es lo suficientemente claro:

¿Quieres salir de este sitio?

Los cambios que realizó no se pueden guardar.

Leave Stay


66
Tenga en cuenta que el uso de cadenas personalizadas ya no funciona en Chrome; chromestatus.com/feature/5349061406228480
amann

55
Sí, eso se describe en la última sección de mi respuesta.
CodeCaster

2
@Chris será porque Angular está manipulando el DOM para cambiar la página, mientras no se aleja del documento actual.
CodeCaster

15
Tenga en cuenta que jQuery areYouSure ha sido abandonado desde 2014 (57 problemas abiertos en Github ), según mi experiencia, está lleno de errores, puede parecer que funciona al principio, pero después de algunas pruebas rápidas me di cuenta de que no siempre funciona. No recomendaría esto en absoluto
Mark

44
@JacopoStanchi Lamentablemente no encontré ninguno. Y quiero decir que parecía bastante, pero esto fue en el 10 de enero, por lo que alguien puede haber escrito algo, pero lo dudo. Su mejor opción es implementarlo usted mismo, no es lo que quiere escuchar, lo siento. (Pero al menos no obtendrá sorpresas como lo hice con jQuery areYouSure.) Además, quién sabe, tal vez incluso podría hacerlo de código abierto y su implementación se compartiría con otros;)
Marque el

75

Consulte el evento JavaScript onbeforeunload . Es un JavaScript no estándar introducido por Microsoft, sin embargo, funciona en la mayoría de los navegadores y su documentación onbeforeunload tiene más información y ejemplos.


3
Creo que se ha convertido en estándares ahora. >> El evento fue presentado originalmente por Microsoft en Internet Explorer 4 y estandarizado en la especificación HTML5.
vee

34

vía 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.
});

Puede Google JQuery Form Serialize, esto recopilará todas las entradas de formulario y lo guardará en una matriz. Supongo que esta explicación es suficiente :)


66
no use #form como id de formulario porque la ventana creará un objeto llamado form :)
mdikici

1
Marque aquí si no funciona para usted: stackoverflow.com/questions/7080269/…
Leniel Maccaferri

16

Solución universal que no requiere configuración que detecte automáticamente todas las modificaciones de entrada, incluidos los elementos contentables:

"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;
    }
});
})();

1
Frijoles fríos. Simplemente copie y pegue este código en su página de prueba, realice un cambio y presione actualizar. Mostrará una alerta de navegador nativo advirtiéndole que tiene cambios sin guardar.
TheLegendaryCopyCoder

1
Esto funcionó para mí en Chrome 71.0.3578.98 (versión oficial) (64 bits)
JacobRossDev

2
Esto funciona muy bien, pero si está utilizando esto con un formulario para el envío, deberá borrar el conjunto de entradas modificadas antes de lo contrario, recibirá una alerta de confirmación de cambios. Agregué un detector de eventos a mi formulario para llamar al enviar, y simplemente ejecuté la función set clear, de esa manera el modificado_inputs está claro cuando se ejecuta antes de descargar el detector de eventos, y permite que la publicación continúe.
stepquick

1
Genial en realidad copiar y pegar. Gracias por ahorrarme tiempo. Trabaja para mí en Firfox 75.0
Connectify_user

1
Me encanta este fragmento
Rawburner

10

Construido sobre la excelente idea de Wasim A. de utilizar la serialización. El problema era que la advertencia también se mostraba cuando se enviaba el formulario. Esto se ha solucionado aquí.

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.'
        }
    });
})

Ha sido probado en Chrome e IE 11.


Wasim A y Eerik Sven Puudist: gracias. Utilicé id para el formulario e id para mi botón de guardar, ya que todos mis botones eran de 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 = "Siguiente"> </td> y pocos more all type submit Por lo tanto, reemplazado .Submit (por clic específico $ ('# save'). clic (function () {isSubmitting = true}) Use '#marksform' en lugar de 'form'
Jayanta

7

Basado en las respuestas anteriores, y unidas desde varios lugares en el desbordamiento de la pila, esta es la solución que se me ocurrió que maneja el caso cuando realmente desea enviar sus cambios:

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 la pena señalar que IE11 parece requerir que la closeEditorWarningfunción regrese undefinedpara que no muestre una alerta.


Esta solución no verifica que los valores cambien de su estado original, lo que invalida en el caso de que el usuario ingrese texto y lo borre antes de intentar navegar.
Brett Weber

Buen punto, @BrettWeber. Puede modificar closeEditorWarning en ese caso y tener "if (window.thisPage.isDirty && uiHasChanged ())", donde uiHasChanged es una función que conoce el estado original del servidor y comprueba todas las diferencias, pero esta solución fue para un caso en el que no quería hacer todo ese trabajo adicional, y esto solo tiene falsos positivos cuando se han presionado las teclas en las áreas de texto, lo que me pareció un compromiso razonable. :)
Jonathan

No debe QC.thisPage.isDirty = false;ser window.thisPage.isDirty = false;? De esa manera, verificará si está enviando el formulario y no mostrará una advertencia. Parecía trabajar para mis pruebas. Además, la mayoría de las formas tienen una en inputlugar de una textarea. Usé lo siguiente, que funciona bastante bien:$("form").on('keyup', 'textarea,input,select', function () {
Mike

7

La siguiente frase ha funcionado para mí.

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

Simplemente configúrelo modifiedcomo verdadero o falso según el estado de su aplicación.


2
Algunas sugerencias: Devuelva un mensaje personalizado en lugar de una cadena vacía, ya que algunos navegadores lo mostrarán (por ejemplo, Edge), y devolverá en undefinedlugar de nullcomo IE imprimirá 'nulo' si modifiedes falso.
Kevin Lee

1
¿Qué hay de los dispositivos móviles? Según tengo entendido, los dispositivos IOS no respetan onbeforeunload.
jaybro

4

El siguiente código funciona muy bien. Debe alcanzar los cambios de entrada de los elementos de su formulario a través del 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;

Lo inserté en un archivo separado y lo incluí con <script src = "warnOnChange.js"> </script> pero no sucede nada cuando modifico un campo de texto y luego ejecuto un comando de encabezado.
Fabrizio Bartolomucci

2

Puede usar serialize () para crear una cadena de texto codificada en URL serializando los valores del formulario y verificar si el formulario ha cambiado antes de la descarga

$(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 enlace https://coderwall.com/p/gny70a/alert-when-leaving-page-with-unsaved-form Escrito por Vladimir Sidorenko


1
Funcionó, pero como respondió el lanzador de códigos, hay algunos defectos con este método, consulte esta explicación stackoverflow.com/a/7317311/10555981
Pradeep

Ya hay un par de respuestas usando serialize(), y de hecho, tiene sus inconvenientes.
CodeCaster

Esta debería ser la respuesta correcta, muy simple de usar y funciona como se esperaba.
Jodyshop

1

Agregando a la idea de @codecaster, podría agregar esto a cada página con un formulario (en mi caso, lo uso de manera global para que solo en los formularios tenga esta advertencia) cambie su función a

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

Además, envíe los formularios, incluidos los enlaces de inicio de sesión y de botones de cancelación, de modo que cuando la persona presione cancelar o enviar el formulario no se active la advertencia también en cada página con un formulario ...

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

1

Puede consultar una explicación detallada aquí: http://techinvestigations.redexp.in/comparison-of-form-values-on-load-and-before-close/ compare-of-form-values-on-load-and antes de cerrar

El 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

Respuesta corta:

let pageModified = true

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

1

La solución 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.'
        }
    });
})

... espontáneamente hizo el trabajo por mí en un entorno complejo orientado a objetos sin ningún cambio necesario.

El único cambio que apliqué fue referirme al formulario concreto (solo un formulario por archivo) llamado "formForm" ('form' -> '#formForm'):

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

Especialmente bien hecho es el hecho de que el botón de enviar se está "dejando solo".

Además, funciona para mí también con la última versión de Firefox (a partir del 7 de febrero de 2019).


1

Probé la solución universal de Eli Grey, solo funcionó después de que simplifiqué el 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;
      }
    });

  })();

Las modificaciones a su se eliminan el uso target[defaultValue]y solo se utilizan target.dataset[defaultValue]para almacenar el valor predeterminado real.

Y agregué un detector de eventos 'guardado' donde el evento 'guardado' lo activará usted mismo cuando su acción de guardado haya tenido éxito.

Pero esta solución 'universal' solo funciona en los navegadores, no funciona en la vista web de la aplicación, por ejemplo, los navegadores WeChat.

Para que funcione en los navegadores WeChat (parcialmente) también, otra mejora nuevamente:

  '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

Lo hice de manera diferente, compartiendo aquí para que alguien pueda obtener ayuda, probada solo con Chrome.

Quería advertir al usuario antes de cerrar la pestaña solo si hay algunos cambios.

<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 bien, pero tengo otro problema, cuando envío el formulario recibo la advertencia no deseada, vi mucha solución, esto se debe a que antes de la descarga se dispara antes del envío, por eso no podemos manejarlo en un evento de envío onbeforeunload = null, pero El evento onclick de los botones de envío se activa antes de estos dos eventos, así que actualicé el 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

En primer lugar, la mayoría de los navegadores tienen esta función por defecto. ¿Y por qué necesitas esto? ¿Por qué no mantener la forma sincronizada? Quiero decir, guárdelo en cualquier cambio sin esperar ningún envío del usuario. Al igual que los contactos de Google. Por supuesto, si solo todos los campos del formulario son obligatorios. A los usuarios no les gusta cuando les obligan a llenar algo sin la oportunidad de irse a pensar si lo necesitan. :)


tendrá razón, pero mis formularios se generan dinámicamente y los campos no están bajo mi control, por lo que para mí no es posible rastrear todos los campos y enviar solicitudes a través de ajax, si tiene algo en mente, comparta conmigo.
Khan

De acuerdo, puede que no sea necesario para sus propósitos, pero aún puede implementarse. Si los elementos del formulario están en la pantalla, puede adjuntar sus propios controladores de eventos y obtener los datos que desee. Luego use AJAX para guardar los datos donde quiera. Incluso si los formularios tienen ID o nombres de clase generados aleatoriamente, puede usar XPaths si puede anticipar la estructura del formulario. Es XML / HTML ¿verdad? Entonces, incluso podría tener un JAD con las personas responsables del formulario generado dinámicamente y hablar sobre cómo XSTL podría beneficiarlos a ambos en este proyecto. Solo un pensamiento ...
SimonDever

1
save it on any change without waiting any submitting from userNo siempre quieres hacer esto. A veces, el usuario quiere hacer muchos cambios y luego revisar y confirmar que quiere guardarlo.
BadHorsie

1
No sugerí enviar el formulario. Los datos podrían guardarse en localStorage, en algún caché o incluso enviarse con algún borrador de bandera. Hay muchos métodos para este comportamiento. Es mucho mejor que alertar al usuario acerca de que no terminó el formulario y si no lo hace y cerrará la ventana, tendrá que volver a llenarlo la próxima vez. "Vamos, hombre, no seas perezoso, tu tren / autobús / avión / etc. no importa tan bien como no nos importa que hayas olvidado un cargador de tu computadora portátil, ¡solo llena este maldito formulario!"
YuS
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.