jquery - stop - Haga clic en disparador en input=archivo en ajax asincrónico hecho()
jquery ajax post (3)
Tengo un formulario con algunos datos y subir. La carga solo se puede iniciar si los datos se recibieron y procesaron correctamente. Para hacer eso, hago una llamada ajax donde
- enviar datos,
- verifica su resultado,
- active un clic () para abrir un cuadro de diálogo de archivo.
Lo último con click () no funciona, ya que parece que la
llamada asincrónica bloquea la apertura de una ventana de carga
.
Solo funciona si configuro
async: false
.
No puedo encontrar nada en la documentación y en este sitio y quiero saber cuál es el problema allí y cómo hacerlo funcionar manteniendo la llamada asincrónica.
Ejemplo:
$.ajax({
type: "POST",
url: "/Save",
data: jsonText,
dataType: "json",
//async: false [1]
}).done(function (msg) {
$("#upload").click();
});
//$("#upload").click(); [2]
Demostración: http://jsfiddle.net/c2v00uxn/
Nota:
- si descomento [1] o [2], funciona (el cuadro de diálogo del archivo aparece como se esperaba).
- reemplazar click () con trigger (''click'') no funciona
- reemplazar click () con live () / on () no ayuda
- el control de carga de archivos es visible como por ejemplo (por lo que no se debe a un control oculto)
- la configuración de tiempo de espera para ajax no ayuda.
ACTUALIZAR
No se trata de cómo hacer un "clic" en general, se trata de cómo hacer clic después de una llamada asíncrona ajax (a partir de ahora, solo funciona con una llamada no asíncrona).
En este momento no es posible abrir una ventana emergente de archivo desde una devolución de llamada asíncrona ajax debido a las características de seguridad recomendadas por w3c en los navegadores.
En el comportamiento de activación del elemento de entrada de archivo, primero verifica si el algoritmo puede mostrar una ventana emergente , si no, entonces aborta los siguientes pasos sin hacer nada más. de w3c.org
Se permite que un algoritmo muestre una ventana emergente si alguna de las siguientes condiciones es verdadera:
-
La tarea en la que se ejecuta el algoritmo actualmente está procesando un comportamiento de activación cuyo
evento de clic fue confiable
(eventos confiables: eventos generados por el agente de usuario, ya sea como resultado de la interacción del usuario o como resultado directo de cambios en el DOM, el agente de usuario confía en los privilegios que no se otorgan a los eventos generados por el script a través del método
DocumentEvent.createEvent("Event")
, modificado mediante el métodoEvent.initEvent()
, o enviado a través deEventTarget.dispatchEvent()
método. El atributo isTrusted de eventos de confianza tiene un valor de verdadero, mientras que los eventos no confiables tienen un valor de atributo isTrusted de falso. de lo contrario, http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120614/#trusted-events ). -
La tarea en la que se ejecuta el algoritmo actualmente ejecuta el detector de eventos para un evento confiable cuyo tipo se encuentra en la siguiente lista:
- cambio
- hacer clic
- dblclick
- mouseup
- Reiniciar
- enviar
- La tarea en la que se ejecuta el algoritmo fue puesta en cola por un algoritmo al que se le permitió mostrar una ventana emergente, y la cadena de dichos algoritmos comenzó dentro de un marco de tiempo definido por el agente de usuario.
En su código, el usuario no activa el evento de clic, sino que lo activa la devolución de llamada completa de ajax.
Aquí el navegador declara que no se puede confiar en el evento para abrir una ventana emergente.
En algunos navegadores, puede ver un atributo
isTrusted
establecido en verdadero si el evento se declara como confiable.
https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted
Nota
Diferentes navegadores atrapan la diferencia entre un clic activado por script y un usuario real usando diferentes métodos.
Lo que puede hacer en este escenario es deshabilitar el botón de entrada de archivo (o todo el formulario) y habilitar después de que ajax haya terminado. De esa forma, el usuario no hará clic en el botón de carga hasta que se complete la solicitud de ajax. A partir de ahora no hay otra manera de hacer ambas cosas con un solo clic, ya que también hay un límite de tiempo para abrir una ventana emergente. Cuando revisé en Chrome, el plazo es de 1000 ms. 1000 ms después de la acción del usuario, la ventana no se abrirá.
JQuery dice que el disparador no funcionará para elementos como la carga y el ancla de archivos. (fuente - https://learn.jquery.com/events/triggering-event-handlers/ )
La función .trigger () no se puede usar para imitar eventos nativos del navegador, como hacer clic en un cuadro de entrada de archivo o una etiqueta de anclaje. Esto se debe a que no hay un controlador de eventos adjunto usando el sistema de eventos de jQuery que corresponde a estos eventos.
En ese caso, es posible que deba crear eventos manualmente utilizando las siguientes funciones de JavaScript.
- document.createEvent
- event.initMouseEvent
- element.dispatchEvent
Un código de muestra + definición para las funciones mencionadas anteriormente se puede encontrar en el sitio para desarrolladores de Mozilla
https://developer.mozilla.org/samples/domref/dispatchEvent.html
Tal vez, esto te ayudará.
Tengo una solución que funciona por ahora. Es un truco, por lo que puede no funcionar en el futuro cercano, ya que evita las características de seguridad mencionadas por Tkay anteriormente.
Presento un tiempo de espera que espera a que la solicitud ajax devuelva los datos que quiero verificar antes de iniciar el diálogo del navegador de archivos.
customFileUploadButton.addEventListener(''click'', function(e) {
var returnValueToCheck; //Value we want to check against
//reference to vanilla JS ajax function that takes callback
ajax(function(ajaxData) {
returnValueToCheck = ajaxData;
});
setTimeout(function() {
if (returnValueToCheck !== undefined) { //dummy check for example
file.click();
} else {
console.log("Criteria not fulfilled");
}
}, 1000);//timer should be larger than AJAX timeout
});
Para ser honesto, no estoy seguro de por qué exactamente esto funciona, aparte de pasar aparentemente las pruebas específicas del navegador que normalmente prohíben este tipo de comportamiento. Por eso lo considero un hack.
Mi ejemplo es vanilla JS, pero debería ser fácil crear una versión jQuery. Vea este JSFiddle para ver un ejemplo completo.
(Esta es mi primera aventura en contribuir, así que por favor comente sobre posibles errores y descuidos)