EDITAR UN ITEM DE UNA TABLA CLICANDO LA CELDA (POR AJAX)
La tabla de clientes la cargamos a través de un while ($registro = mysqli_fetch_array ($sqldevolucion, MYSQLI_ASSOC)) como siempre pero en este caso todo por echo()por lo complejo de la carga de registros.
El id de cada <tr> lo ponemos al campo id de la tabla asi vamos a poder diferenciar sobre que celda clicamos la clase .entrada va con el trigger dblclick y .volver nos va a servir para guardar el contenido cuando no lo editemos, son obligadas para el script.
Si una dirección está en blanco cargo un espacio &nbsp; htmlchar. para que no quede una div vacía que no detecta eventos con:
if(strlen($registro["direccion"])==0){
        $direccion="&nbsp;";
}else{
        $direccion=$registro["direccion"];
}
Por supuesto que la solución ideal para codificar menos (el if en la carga) es que todos los valores de tipo varchar y text tengan &nbsp; como default, fechas NULL que aparecen como 0000-00-00
Lo mismo vamos a hacer en el script php si borré una dirección cargo un espacio en blanco con
if(strlen($valor)==0){
     $valor="&nbsp";
}

SCRIPT JQUERY

Doble click sobre la dirección

1) $('body').on('dblclick','.entrada', function(e){ si no burbujeamos desde body después de una edición ya no responde la div recargada por script, porque no está cargada en la DOM inicial.
2) id= $(this).parents('tr').attr('id'); En este caso $(this) es la div .entrada, parents('tr') busca el primer tr que encuentre hacia arriba y .attr('id') el id de esa fila (que es el de la dirección obviamente).
3) contenido= $(this).html(); copia en la var contenido(global por declararla fuera de la función, la vamos a necesitar luego en blur) el valor de la dirección contenida en la div clicada (this).
4) temp = $(this).parent().html(); En temp (global) se copia TODO el html porque parent es la etiqueta superior a this o sea <td class='volver'> así en temp queda todo el html de la div con la dirección original, la guardamos por si no hay edición para reponerla sin más.
5) "<input class='cambio' type='text' value='" + contenido + "' />"; a la var entrada le doy el valor de un input clase .cambio para manejarla y de val = contenido (o sea la dirección actual). luego $(this).parent().html(entrada); convierto la div en input con contenido igual al valor de la <div> clicada. Recordar que this.parent es el <td class='volver'>.
5') Finalmente le doy foco con $('.cambio').focus();

Click sobre cualquier parte excepto la dirección

6) $('body').on('blur','.cambio', function(e){ Cuando abandono el input .cambio (click fuera de él). (Igual tema de burbujear de body). 7) if ($(this).val()==contenido){ si no cambie el valor (el original que guardé en contenido es igual al valor del input $(this)). 8) $('#'+id).find('.volver').html(temp); Esta linea funciona así: $('#'+id) va al <tr> de la fila en que estamos (porque así lo cargamos por php en la tabla, ver arriba) find('.volver') busca dentro de esa <tr> la etiqueta que tenga la clase '.volver' que es el input que NO editamos y por eso .html(temp) lo sobreescribe con la div original que guardamos en temp (pero como esta div aparece en el DOM después de la carga inicial los eventos directos sobre ella no funcionan, por esto debemos burbujear los eventos desde body "punto 1)").
9) Si cambió el valor var nuevovalor = $(this).val(); guarda el valor editado
declaramos var espera como la div pero con un gif animado de espera.
10) $('#'+id).find('.volver').html(espera) lo mismo que en 8) pero lo que pongo es la div con el gif de espera
11) Mando por AJAX el par id y nuevovalor con data: 'valor=' + nuevovalor + '&id=' + id, (ej: valor=Cruz 566&id=2 ) a procesar, (ver código PHP más abajo, primero un UPDATE, luego un SELECT para asegurarme que se cambió con éxito y devuelvo el valor nuevo por JSON ej:{"newvalor":"Cruz 705"}).
12) Con $('#'+id).find('.volver').html("<div class='entrada'>" + data.newvalor + "</div>"); sustituyo ahora el esperar por una div como la original pero con el valor devuelto por JSON, que es el actual en la base de datos (data.newvalor).
						
<!--************************HTML CARGAR LA TABLA******************************-->
<head>
<?php  
	include("conexion.php");	 // abre la conexión a la base de datos
	global $conn; 				 //lo usamos en conexion, lo declaramos acá para no llamar siempre a $GLOBALS[]
?>
</head>
<body>
<table id="tabla">
  			<tr>
				<td>ID</td>
    			<td>NOMBRE</td>
    			<td>DIRECCION</td>
				<td>MAIL</td>
    			<td>NACIMIENTO</td>
  			</tr>
			<?php 
			if(conectar()){
				mysqli_set_charset($conn, "utf8mb4");
				$sqltxt = "SELECT * FROM clientes LIMIT 0,15";
				$sqldevolucion = mysqli_query($conn,$sqltxt);
				if (!mysqli_num_rows($sqldevolucion)) {
                	echo("Error, no se devuelven registros");
				} else {
                    while ($registro = mysqli_fetch_array($sqldevolucion, MYSQLI_ASSOC)){
						if(strlen($registro["direccion"])==0){
							$direccion="&nbsp";
						}else{
							$direccion=$registro["direccion"];
						}
						echo("<tr id='" . $registro["id"] . "'>");
							echo("<td class='filaid'>" . $registro["id"] . "</td>" );
							echo("<td>".$registro["nombre"] . "</td>" );
							echo("<td class='volver'> <div class='entrada'>" . $direccion . "</div></td>" );
							echo("<td>".$registro["mail"] . "</td>" );
							echo("<td style=' text-align:center;'>".$registro["fecha_nac"]  . "</td>" );
						echo("</tr>");
						
					}
					mysqli_free_result($sqldevolucion);	//devuelvo recurso a memoria
					mysqli_close($conn);				// cierro conexion
				}
			}else{
				echo(mysqli_error($conn));
			}
			?>
		</table>
</body>
		


<!--*********************SCRIPT JQUERY  (AJAX)*******************************-->

<head>
	<script>
	$(document).ready(function(){
		var id=0;											//declaro acá para que sean globales
		var contenido;
		var temp; 

		$('body').on('dblclick','.entrada', function(e){    //1-usamos esta y no la de abajo porque si no en la segunda 
		//	$('.entrada').on('dblclick', function(e){		dblclick no va a responder porque .entrada no se cargo en el DOM inicial
						
			id= $(this).parents('tr').attr('id');   	//2-obtiene el id del <tr> o sea de la fila del clicado
			contenido= $(this).html();					//3-obtiene el contenido de la <div> clicada
			temp = $(this).parent().html();				//4-guarda el html completo de la celda por si no hay cambios
			var entrada = "<input class='cambio' type='text' value='" + contenido + "' />";
			$(this).parent().html(entrada);				// 5-convierto la div en input con contenido igual al valor de la <div> clicada
			$('.cambio').focus();						//le da foco al input
		});

		$('body').on('blur','.cambio', function(e){		//6-igual que dblclick pero al salir del input
			if ($(this).val()==contenido){				//7- si no cambie el valor
				$('#'+id).find('.volver').html(temp);   //8-vuelve al contenido original si no se cambió nada (volver es el td)
				 										//que contiene la div o el input
			}else{
				var nuevovalor = $(this).val();			// 9-guardo el valor editado
				var espera = "<div class='entrada' style='text-align:center;'><img src='esperando.gif' width='16' height='16'/></div>";
				$('#'+id).find('.volver').html(espera);	// 10-pongo el gif de esperar
				$.ajax({  
					type: "POST",  
					url: "tec-php-editar-item-tabla-procesar01.php",  
					data: 'valor=' + nuevovalor + '&id=' + id, 			//11-POSTeo el par valor/id 
					dataType:'json',
					success: function(data) { 
						$('#'+id).find('.volver').html("<div class='entrada'>" + data.newvalor + "</div>");
					},		// 12-sustituyo el input por una div con el valor que devuelve procesar
					error: function(request,error) {
						$("#msg").html("ha ocurrido un error al editar la dirección");
						$('#'+id).find('.volver').html(temp);   //13- si no se pudo editar repongo div con el valor antiguo
					}
				});    //fin ajax         
			}
		});	
 	});
	</script>
	<style>
	</style>
</head>

<!--********SCRIPT PROCESAR.PHP RECIBE ID Y DEVUELVE ARRAY CON EL NUEVO VALOR*********-->

<?php
include("conexion.php");	 // abre la conexión a la base de datos
global $conn;  //lo usamos en conexion, lo declaramos acá para no llamar siempre a $GLOBALS[]
	$valor=$_POST["valor"];    // se recupera el valor pasado de ajax por post  
	$id=$_POST["id"];
	if(conectar()){
		mysqli_set_charset($conn, "utf8mb4");						// me aseguro que el charset sea el de la database
		if(strlen($valor)==0){										// si borré una dirección cargo un espacio en blanco		
				$valor=" ";
		}
		$sqltxt="UPDATE clientes SET direccion='" . $valor . "' WHERE id=" . $id;
        $sqldevolucion = mysqli_query($conn,$sqltxt);
		$sqltxt="SELECT direccion FROM clientes WHERE id=" . $id;   //chequeo que se haya modificado
        $sqldevolucion = mysqli_query($conn,$sqltxt);
		$registro = mysqli_fetch_array($sqldevolucion, MYSQLI_ASSOC);
		$resultado = array("newvalor" => $registro["direccion"]);
		mysqli_close($conn);				 // cierro conexion		
		echo(json_encode($resultado));
	}

?>
					
					
© IQSystems 2023