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 htmlchar. para que no quede una div vacía que no
detecta eventos con:
if(strlen($registro["direccion"])==0){
$direccion=" ";
}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 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=" ";
}
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=" ";
}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));
}
?>