Reemplazando un elemento y devolviendo el nuevo en jQuery

¿Cómo se reemplaza un elemento en jQuery y se devuelve el elemento de reemplazo en lugar del elemento que se eliminó?

Tengo el siguiente escenario. Tengo muchas casillas de verificación y una vez que hace clic en una de ellas, esa casilla se sustituye por un icono de carga. Una vez que suceden algunas cosas de AJAX, el icono de carga se reemplaza por un icono de marca.

Usando jQuery’s replaceWith , harías algo como:

 $("input[type='checkbox']").click(function() { $(this).replaceWith("loading"); $.post("somepage.php"); $(this).replaceWith("done"); }); 

Sin embargo, esto no funciona porque replaceWith devuelve el elemento que se eliminó, no el que se agregó. Entonces, una vez que se complete el material AJAX, https://stackoverflow.com/questions/892861/replacing-an-element-and-returning-the-new-one-in-jquery/loading.jpg permanecerá allí para siempre.

¿Hay alguna manera de que pueda devolver el elemento de reemplazo sin seleccionarlo?

Gracias por adelantado.

Asigne una clase a la imagen de carga, luego en la callback posterior, use la clase como selector para encontrar la imagen que acaba de inyectar.

 $("input[type='checkbox']").click(function() { $(this).replaceWith("loading"); $.post("somepage.php", function() { $('.loading-image').replaceWith("done"); }); }); 

Si puede tener varios de estos ejecutando a la vez, puede obtener el padre más cercano de this y usarlo como contexto cuando busque la clase.

EDITAR : Otra alternativa que usa una variable para almacenar el nuevo elemento y elimina la necesidad de aplicar la clase y buscar el nuevo elemento cuando la función regresa.

 $("input[type='checkbox']").click(function() { var loading = $("loading"); $(this).replaceWith(loading); $.post("somepage.php", function() { loading.replaceWith("done"); }); }); 

Cree un elemento y utilícelo como parámetro para reemplazar con:

$('input[type=checkbox]').click(function() { var img = document.createElement('img'); img.src = 'http://sofes.miximages.com/replace/loading.jpg'; $(this).replaceWith(img); $.post('somepage.php', function() { $(img).replaceWith('done'); }); });
$('input[type=checkbox]').click(function() { var img = document.createElement('img'); img.src = 'http://sofes.miximages.com/replace/loading.jpg'; $(this).replaceWith(img); $.post('somepage.php', function() { $(img).replaceWith('done'); }); }); 

Podrías darle una identificación única usando el índice:

 $("input[type='checkbox']").click(function() { var index = $("input[type='checkbox']").index(this); $(this).replaceWith("loading"); $.post("somepage.php"); $('#myLoadingImage'+index).replaceWith("done"); }); 

La razón por la que su código no funciona es que el primer replaceWith reemplaza el elemento al que se refiere. El segundo replaceWith intenta reemplazarlo nuevamente, pero como ya se ha ido, no hay nada que reemplazar. Y el icono de tick no se mostrará.

Lo mejor es usar la función de callback posterior que sugiere tvanfosson.

Mira esto.

 $.fn.replaceWithMod = function(obj) { var $a = $(obj); this.replaceWith($a); return $a; }; var newObj = $('a').replaceWithMod('
New Created Object
'); $(newObj).css('color','green');

Escribí un pequeño complemento para lograr un resultado similar porque me gusta poder recuperar un puntero para el nuevo elemento en una línea de código.

 (function($){ $.fn['overwrite'] = function(target){ $(target).replaceWith(this); return this; } }(jQuery)); 

Ejemplo de uso:

 $("input[type='checkbox']").click(function() { var $loading = $("loading").overwrite( this ); $.post("somepage.php", function() { $loading.replaceWith("done"); }); }); 

Si no hay necesidad de utilizar específicamente el método replaceWith, puede usar el método replaceAll que es lo contrario a replaceWith.

Vea la respuesta aquí: (respuesta a una pregunta similar hecha un año más tarde) replaceAll reemplaza cada elemento en el objeto pasado como parámetro o los elementos que coinciden con el selector pasado como parámetro con los elementos coincidentes y devuelve los elementos coincidentes (el nuevo contenido ).

De esa manera, la edición en la respuesta de tvanfosson (y el código en la respuesta del Guardián) se vería así:

 $("input[type='checkbox']").click(function() { var loading = $("loading").replaceAll($(this)); $.post("somepage.php", function() { loading.replaceWith("done"); }); }); 

Es solo una línea más corta, pero por brevedad y para incluir la opción de usar replaceAll (), consideré oportuno agregar esta respuesta a esta pregunta antigua y más vista.

¿Por qué no hacer un objeto jquery intermedio, como este? …

 $("input[type='checkbox']").click(function() { var insertedElement = $("loading"); $(this).replaceWith(insertedElement); $.post("somepage.php"); var anotherInsertedElement = $("done"); $(this).replaceWith(anotherInsertedElement); //do something with either of the inserted elements });