I do not receive JSON data

1

I have a problem receiving JSON data from a form connected to a database with fields ( id , nombre , numero ).

The problem arises when I try to edit a table value and save it and it should be updated through XHR.

Could someone tell me what error / is there?

The error that it gives in console is:

  

Uncaught SyntaxError: Unexpected token s in JSON at position 0           at JSON.parse ()           at XMLHttpRequest.xhr.onreadystatechange app.js377

index.php

<?php
   try {
        require_once('funciones/bd_conexion.php');
        $sql = 'SELECT * FROM contactos'; 
        $resultado = $conn->query($sql);
   } catch (Exception $e) {
         $error = $e->getMessage();
   } 
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Agenda PHP</title>
<link href="https://fonts.googleapis.com/css?family=Proza+Libre" rel="stylesheet">
<link rel="stylesheet" href="css/estilos.css" media="screen" title="no title">
</head>
<body>
<div class="contenedor">
  <h1>Agenda de Contactos</h1>
  <div class="contenido">
    <div id="crear_contacto" class="crear">
      <h2>Nuevo Contacto</h2>
      <form action="crear.php" method="post" id="formulario-crear-usuario">
        <div class="campo">
          <label for="nombre">Nombre:</label>
          <input type="text" name="nombre" id="nombre" placeholder="Nombre">
        </div>
        <div class="campo">
          <label for="numero">Teléfono:</label>
          <input type="text" name="numero" id="numero" placeholder="Número">
        </div>
        <input type="submit" value="Agregar" id="agregar" class="boton">
      </form>

    </div>
    <!--.crear_contacto--> 
  </div>
  <!--.contenido-->

  <div class="contenido existentes">
    <div class="buscar">
      <h2>Buscar</h2>
      <input type="text" id="buscador" name="buscador" placeholder="Buscar" class="buscador">
    </div>
    <h2>Contactos Existentes</h2>
    <p>Resultados: <span id="total"><?php echo $resultado->num_rows; ?></span> </p>
    <table id="registrados">
      <thead>
        <tr>
          <th>Nombre</th>
          <th>Teléfono</th>
          <th>Editar</th>
          <th> <button type="button" name="Borrar" id="btn_borrar" class="borrar">Borrar</button>
            <input type="checkbox" id="borrar_todos">
          </th>
        </tr>
      </thead>
      <tbody>
        <?php //fetch_assoc, fetch_row, fetch_array, fetch_all, fetch_objects  ?>
        <?php while($registros = $resultado->fetch_assoc() ) { ?>
        <?php //dentro parentesis (MYSQLI_ASSOC, MYSQLI_NUM) ?>
        <tr id="<?php echo $registros['id']; ?>">   
          <td>
            <p><?php echo $registros['nombre']; ?></p>
            <input type="text" class="nombre_contacto" value="<?php echo $registros['nombre']; ?>" name="contacto_<?php echo $registros['id']; ?>">
          </td>
          <td>
            <p><?php echo $registros['numero']; ?></p>
            <input type="text" class="telefono_contacto" value="<?php echo $registros['numero']; ?>" name="telefono_<?php echo $registros['id']; ?>">
            </td>
          <td>
            <!--<a href="editar.php?id=<?php echo $registros['id']; ?>">Editar</a> cambia en v449-->
            <a href="#" class="editarBtn">Editar</a>
            <a href="#" class="guardarBtn">Guardar</a>
          </td>
          <td class="borrar"><input class="borrar_contacto" type="checkbox" name="<?php echo $registros['id']; ?>"></td>
        </tr>
        <?php } ?>
      </tbody>
    </table>
  </div>
</div>
<?php 
    $conn->close();
?>
<script src="js/app.js"></script>
</body>
</html>

In this file especially the problem would come in the last two functions actualizarRegistro(idRegistro) and actualizarAjax(datosContacto) .

app.js

var agregarContacto = document.getElementById('agregar');
var formulario = document.getElementById('formulario-crear-usuario');
var action = formulario.getAttribute('action');
var divCrear = document.getElementById('crear_contacto');
var tablaRegistrados = document.getElementById('registrados');
var checkboxes = document.getElementsByClassName('borrar_contacto');
var btn_borrar = document.getElementById('btn_borrar');
var tableBody = document.getElementsByTagName('tbody');
var divExistentes = document.getElementsByClassName('existentes');
var inputBuscador = document.getElementById('buscador');
var totalRegistros = document.getElementById('total');
var checkTodos = document.getElementById('borrar_todos');

function registroExitoso(nombre){
    //crear div y agregar un id
    var divMensaje = document.createElement('DIV');
    divMensaje.setAttribute('id',"mensaje");

    //agregar texto
    var texto = document.createTextNode('Creado: ' + nombre);
    divMensaje.appendChild(texto);

    divCrear.insertBefore(divMensaje, divCrear.childNodes[4]);

    //agregar la clase mostrar
    divMensaje.classList.add('mostrar');

    //ocultar el mensaje de creacion
    setTimeout(function(){
        divMensaje.classList.add('ocultar');
        setTimeout(function(){
            var divPadreMensaje = divMensaje.parentNode;
            divPadreMensaje.removeChild(divMensaje);
        }, 500);
    }, 3000);
}
// construir template para insertar datos dinamicamente
function construirTemplate(nombre, telefono, registro_id){
    //crear nombre de contacto
    var tdNombre = document.createElement('TD');
    var textoNombre = document.createTextNode(nombre);
    tdNombre.appendChild(textoNombre);

    //crear telefono de contacto
    var tdTelefono = document.createElement('TD');
    var textoTelefono = document.createTextNode(telefono);
    tdTelefono.appendChild(textoTelefono);

    //crear enlace para editar
    var nodoBtn = document.createElement('A');
    var textoEnlace = document.createTextNode('Editar');
    nodoBtn.appendChild(textoEnlace);
    nodoBtn.href = 'editar.php?id=' + registro_id;

    //agregar el boton al td
    var nodoTdEditar = document.createElement('TD');
    nodoTdEditar.appendChild(nodoBtn);

    //crear checkbox para borrar
    var checkBorrar = document.createElement('INPUT');
    checkBorrar.type = 'checkbox';
    checkBorrar.name = registro_id;
    checkBorrar.classList.add('borrar_contacto');

    //agregar td a checkbox
    var tdCheckbox = document.createElement('TD');
    tdCheckbox.classList.add('borrar');
    tdCheckbox.appendChild(checkBorrar);

    //Crear Input con el nombre v449
    var inputNombre = document.createElement('INPUT');
    inputNombre.type = 'text';
    inputNombre.name = 'contacto_' + registro_id;
    inputNombre.value = nombre;

    //Crear Input con el telefono v449
    var inputTelefono = document.createElement('INPUT');
    inputTelefono.type = 'text';
    inputTelefono.name = 'contacto_' + registro_id;
    inputTelefono.value = nombre;

    tdNombre.appendChild(inputNombre);
    tdTelefono.appendChild(inputTelefono);

    //agregar al tr 
    var trContacto = document.createElement('TR');
    var idTr = trContacto.setAttribute('id', registro_id);//borrar ultimo
    var miId = trContacto.attributes[0].nodeValue;//borrar ultimo
    trContacto.appendChild(tdNombre);
    trContacto.appendChild(tdTelefono);
    trContacto.appendChild(nodoTdEditar);
    trContacto.appendChild(tdCheckbox);

    tablaRegistrados.childNodes[3].append(trContacto);

    //no viene en vid -> se mueve el for dentro del crearTemplate para que pinte en rojo un contacto añadido nuevo
    for(var i = 0; i < checkboxes.length; i++){
        checkboxes[i].addEventListener('change', function(){
            //console.log("has hecho click en un checkbox");
            if(this.checked){
                //console.log("Checkbox CHECADO");
                this.parentNode.parentNode.classList.add('activo');
            } else {
                console.log("Checkbox no CHECADO");
                this.parentNode.parentNode.classList.remove('activo');
            }
        });
    }
}

function crearUsuario(){
    //alert("funciona");
    var form_datos = new FormData(formulario);
    for([key, value] of form_datos.entries()){
        console.log(key + ": " + value);
    }
    var xhr = new XMLHttpRequest();
    xhr.open('POST', action, true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            var resultado = xhr.responseText;
            console.log(resultado);
            var json = JSON.parse(resultado);
            //console.log(json.respuesta);
            if(json.respuesta == true){
                //alert("Contacto creado exitosamente");
                registroExitoso(json.nombre);
                construirTemplate(json.nombre, json.telefono, json.id);
                //añadido en v445
                var totalActualizado = parseInt(totalRegistros.textContent) + 1;
                totalRegistros.innerHTML = totalActualizado;
            }
        }
    }
    xhr.send(form_datos);
}

function mostrarEliminado() {
    // crear div y agregar id
    var divEliminado = document.createElement('DIV');
    divEliminado.setAttribute('id','borrado');

    //agregar texto
    var texto = document.createTextNode('Eliminado de lista de contactos');
    divEliminado.appendChild(texto);

    divExistentes[0].insertBefore(divEliminado, divExistentes[0].childNodes[0]);

    //agregar clase de CSS
    divEliminado.classList.add('mostrar');

    //ocultar el mensaje de borrado
    setTimeout(function() {
        divEliminado.classList.add('ocultar');
        setTimeout(function() {
            var divPadreMensaje = divEliminado.parentNode;
            divPadreMensaje.removeChild(divEliminado);
        }, 500 );
    }, 3000);
}

function eliminarHTML(ids_borrados){
    console.log("Id a borrar: " + ids_borrados);
    for(i = 0; i < ids_borrados.length; i++){
        var elementoBorrar = document.getElementById(ids_borrados[i]);
        tableBody[0].removeChild(elementoBorrar);
    }
}

function contactosEliminar(contactos){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'borrar.php?id=' + contactos, true);
    console.log('borrar.php?id=' + contactos);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            var resultadoBorrar = xhr.responseText;
            var json = JSON.parse(resultadoBorrar);
            if(json.respuesta == false) {
                alert("selecciona un elemento");
            } else {
                console.log("Resultado: " + resultadoBorrar);
                //console.log('SQL' + json.sql);
                eliminarHTML(contactos);
                mostrarEliminado();
                var totalActualizado = parseInt(totalRegistros.textContent) - json.borrados;
                totalRegistros.innerHTML = totalActualizado;
            }
        }
    };
    xhr.send();
}

function checkboxSeleccionado() {
    var contactos = [];
    for(i = 0; i < checkboxes.length; i++){
        if(checkboxes[i].checked  == true){
            contactos.push(checkboxes[i].name);
        }
    }
    //console.log(contactos);
     contactosEliminar(contactos);
}

//añadido lesli
for(var i =0; i < checkboxes.length; i++){
checkboxes[i].addEventListener('change',function(){
//console.log("Has seleccionado un checkbox");
if(this.checked){
this.parentNode.parentNode.classList.add('activo');
//console.log("Checkbox checado");
}else{
// console.log("Checkbox no checado");
this.parentNode.parentNode.classList.remove('activo');
}
});
}//fin añadido

agregarContacto.addEventListener('click', function(e){
    e.preventDefault();
    crearUsuario();
});

btn_borrar.addEventListener('click', function(){
    checkboxSeleccionado();
});

function actualizarNumero(){
    var registros = tableBody[0].getElementsByTagName('tr');

    var cantidad = 0;
    var ocultos = 0;

    for( var i = 0; i < registros.length; i++) {
        var elementos = registros[i];
        if(elementos.style.display == 'table-row'){
            cantidad++;
            totalRegistros.innerHTML = cantidad;
        } else {
            if(elementos.style.display == 'none') {
                ocultos++;
                if(ocultos == registros.length) {
                    ocultos -= registros.length;
                    totalRegistros.innerHTML = ocultos;
                }
            }
        }
    }
}

//vid443
function ocultarRegistros(nombre_buscar){
    //console.log(nombre_buscar);
    //variable para todos los registros
    var registros = tableBody[0].getElementsByTagName('tr');

    //expresion regular que busca el nombre con case insensitive (i)
    var expression = new RegExp(nombre_buscar, "i");

    for(var i = 0; i < registros.length; i++){
        registros[i].classList.add('ocultar');//added in v447
        registros[i].style.display = 'none';

        if(registros[i].childNodes[1].textContent.replace(/\s/g, "").search(expression) != -1 || nombre == '') {
            registros[i].classList.add('mostrar');
            registros[i].classList.remove('ocultar');
            registros[i].style.display = 'table-row';
        } //else if(nombre == '') {
            //registros[i].style.display = 'table-row';}
    }
    actualizarNumero();
}

inputBuscador.addEventListener('input', function() {
    //console.log(inputBuscador.value);
    ocultarRegistros(this.value);
});

//Seleccionar todos
checkTodos.addEventListener("click", function(){
    if(this.checked){
        var todosRegistros = tableBody[0].getElementsByTagName('tr');
        for(var i = 0; i < checkboxes.length; i++){
            checkboxes[i].checked = true;
            todosRegistros[i].classList.add('activo');
            }
        } else {
            var todosRegistros = tableBody[0].getElementsByTagName('tr');
            for(var i = 0; i < checkboxes.length; i++){
                checkboxes[i].checked = false;
                todosRegistros[i].classList.remove('activo');
        }
    }
});

/*** Editar registros ***/

function recorrerBotonesEditar(){ //v450
    var btn_editar = tableBody[0].querySelectorAll('.editarBtn');
    //console.log(btn_editar);

    for(var i = 0; i < btn_editar.length; i++) {
        btn_editar[i].addEventListener('click', function(event) {
            event.preventDefault();
            deshabilitarEdicion(); //v451

            //alert("hasta aqui bien");
            var registroActivo = this.parentNode.parentNode;
            //console.log(registroActivo);
            registroActivo.classList.add('modo-edicion');   
            registroActivo.classList.remove('desactivado'); 
            //console.log(registroActivo.id);

            //Actualizamos el registro en especifico (solo uno) v452
            actualizarRegistro(registroActivo.id);  
        });
    }
}

function deshabilitarEdicion(){
    var registrosTr = document.querySelectorAll('#registrados tbody tr');
    //console.log(registrosTr);
    for(var i = 0; i < registrosTr.length; i++){
        registrosTr[i].classList.add('desactivado');
    }
}

function actualizarRegistro(idRegistro){ //v452
    //console.log(idRegistro);
    //Seleccionar Boton de Guardar del Registro en especifico (se pasa el id)
    var btnGuardar = document.getElementById(idRegistro).getElementsByClassName('guardarBtn');
    //console.log(btnGuardar);
    btnGuardar[0].addEventListener('click', function(e){
        e.preventDefault();
        //alert("Click en Guardar!");

        //Obtiene el valor del campo nombre
        var inputNombreNuevo = document.getElementById(idRegistro).getElementsByClassName('nombre_contacto');
        //console.log(inputNombreNuevo);
        var nombreNuevo = inputNombreNuevo[0].value;
        //console.log(nombreNuevo);

        //Obtiene el valor del campo de telefono
        var inputTelefonoNuevo = document.getElementById(idRegistro).getElementsByClassName('telefono_contacto');
        var telefonoNuevo = inputTelefonoNuevo[0].value;
        //console.log(telefonoNuevo);

        //objeto con todos los datos
        var contacto = {
            nombre: nombreNuevo,
            //telefono: telefonoNuevo, //esto fallaba
            numero: telefonoNuevo,
            id: idRegistro
        };
        //console.log(contacto);
        actualizarAjax(contacto); //v453

    });
}

function actualizarAjax(datosContacto){ //v453
    //console.log(datosContacto);
    //Convierte objeto a JSON
    var jsonContacto = JSON.stringify(datosContacto); 
    //console.log(jsonContacto);
    //crear la conexion
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'actualizar.php?datos=' + jsonContacto, true);
    //console.log('borrar.php?id=' + contactos);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
            var resultado = xhr.responseText;
            //var json = JSON.parse(resultadoBorrar);
            var resultadoJson = JSON.parse(resultado);
            console.log(resultadoJson);
        }
    };
    xhr.send();
}

document.addEventListener('DOMContentLoaded', function(event){
    recorrerBotonesEditar();
});

refresh.php

<?php
    function peticion_ajax(){
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';   
    }

    $datos=$_GET['datos'];
    var_dump($datos);
    $datos=json_decode($datos,true);
    var_dump($datos);

   //$nombre = $_GET['nombre'];
   //$numero  =  $_GET['numero'];
   //$id = $_GET['id'];
   $nombre = $datos['nombre'];
   $numero  =  $datos['numero'];
   $id = $datos['id'];

   if(peticion_ajax()){
       try {
            require_once('funciones/bd_conexion.php');
            $sql = "UPDATE contactos SET ";   
            $sql .= "nombre= '{$nombre}', "; 
            $sql .= "numero = '{$numero}' ";
            $sql .= "WHERE id = {$id}";

            $resultado = $conn->query($sql);
            echo json_encode(array(
                'respuesta' => $resultado
            ));

       } catch (Exception $e) {
           $error = $e->getMessage();
       }

        $conn->close();
   } else {
       exit;
   }
?>

styles.css

html {
  box-sizing: border-box;
}
*, *:after, *:before {
  box-sizing: inherit;
  margin:0;
  padding:0;
}

body {
  background-color: orange;
}
.contenedor {
  max-width:1000px;
  margin:0 auto;
  padding: 20px;
  background-color: #ffffff;
}
h1, h2 {
  text-align: center;
  font-family: 'Proza Libre', sans-serif;
}
div.contenido {
  width: 60%;
  margin: 30px auto 0 auto;
  font-size: 24px;
}

h1 {
  font-size: 30px;

}
h2 {
  font-size: 20px;
}
div.crear {
  padding: 20px;
  background-color: #e1e1e1;
}

div.campo {
  margin-bottom: 20px;
}
div.campo label {
  width: 80px;
  display: inline-block;
  float:left;
  margin-top:8px;
  font-size: 16px;
  font-family: Arial, Helvetica, Serif;
  text-transform:uppercase;
  font-size:14px;
  font-weight:bold;
  text-align:right;
  margin-right:20px;
}
div.campo input{
    height:30px;
    width:70%;
    padding:10px;
}
.boton{
    background-color:orange;
    border:none;
    padding:10px 30px;
    cursor:pointer;
    color:white;
    font-size:16px;
    text-transform:uppercase;
}
div.buscar{
    margin-bottom:20px;
}
div.buscar h2{
    margin-bottom:10px;
}
.buscador{
    width:100%;
    padding:10px;
}
span#total{
    font-weight:bold;
    font-family: arial,helvetica,sans-serif;
}
div.existentes {
  padding: 20px;
  background-color: #e1e1e1;
}
div.existentes  table {
  width: 100%;
  font-family: geneva;
  font-size: 16px;
  border-collapse: collapse;
}
div.existentes  table thead {
  background-color: #ff9800;
}
div.existentes table thead th {
    padding:10px 0;
}
div.existentes table tbody tr:nth-child(even) {
  background-color: #9e9e9e;
}
div.existentes  table a {
  background-color: #3f51b5;
  padding: 5px 10px;
  display: block;
  text-align: center;
  color: #ffffff;
  text-transform: uppercase;
  text-decoration: none;
}
div.existentes  table td {
  padding: 10px 0;
  line-height: 20px;
}
div.existentes h2 {
  margin-bottom: 20px;
}
div.existentes p {
  text-align: center;
  margin-bottom: 20px;
}
td.borrar a {
  background-color: red!important;
}

a.volver {
  color: orange;
  text-decoration: none;
  font-weight: bold;
}

div#mensaje{
    margin-top:10px;
    border:1px solid green;
    height:50px;
    line-height:50px;
    text-align:center;
    text-transform:uppercase;
    background-color:green;
    color:white;
    font-family:arial,helvetica,sans-serif;
    border-radius:10px;
    opacity:0;
}

div#borrado {
    background-color: red;
    padding: 10px;
    text-align:center;
    color:white;
    text-transform:uppercase;
    font-weight:bold;
    font-family:arial, helvetica, sans-serif;
    font-size 16px;
}

@keyframes mostrar{
    0% {opacity:0;}
    100% {opacity:1;}
}
@keyframes ocultar{
    0% {opacity:1;}
    100% {opacity:0;}
}
.mostrar {
    animation: mostrar .5s ease-in 1 forwards;
}
.ocultar {
    animation: ocultar .5s ease-in 1 forwards;
}
button.borrar {
    background-color:transparent;
    border:none;
    background-image:url(../img/borrar.png);
    background-position:center center;
    background-repeat:no-repeat;
    background-size:25px;
    text-indent:-9999px;
    display:block;
    height:25px;
    width:25px;
    cursor:pointer;
    margin:0 auto;
    padding:10px;
}
td.borrar input {
    margin: 0 auto;
    display: block;
}
.activo{
    background-color: red!important;
}

/** Modo Edicion **/

.modo-edicion p,
.modo-edicion .editarBtn,
tbody tr input[type="text"],
div.existentes table tr a.guardarBtn {
    display: none;  
}
.modo-edicion input[type="text"],
div.existentes table tr.modo-edicion a.guardarBtn{
    display: block;
}
.desactivado {
    pointer-events:none;
    cursor: default;
    opacity: .5;
}

bd_conexion.php

<?php 
    $conn = new mysqli('localhost', 'root', '', 'miweb');

    if($conn->connect_error) {
      echo $error = $conn->connect_error;
    }

    function peticion_ajax(){
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
    }

?>
    
asked by RicardoKra 30.05.2018 в 13:36
source

1 answer

2

You have a problem mounting the query GET because you do not correctly escape the data:

xhr.open('GET', 'actualizar.php?datos=' + jsonContacto, true);

The correct way would be using encodeURIComponent() :

xhr.open('GET', 'actualizar.php?datos=' + encodeURIComponent(jsonContacto), true);

In PHP, remove the two lines they put:

var_dump($datos);

Also, as we have discovered the tests made in the comments, you should remove the double definition of the function peticion_ajax to avoid sending an error message by defining the same function twice.

If you do not correct the code and avoid sending debugging data, warning or error texts, PHP will generate information that is not part of the JSON, preventing your code from interpreting what PHP generates as a valid JSON. .

    
answered by 30.05.2018 / 14:35
source