Instant search through an input with autocomplete (select)

0

I have a little problem with a part of the code.

I try to do an instantaneous search that when entering data (registration) through an input, show (as verification) that the registration exists and show the name of the person who has that registration.

It works well at the time of writing ( keyup ) ... but it happens that additionally I added an autocomplete ( select ), and the problem is that when I write (ex: 2 characters) ... and I want select one of the autocomplete options ( select ). At the moment of filling in the input field ... the instant search is listed as if it had been written alone (the 2 characters, following the example).

How could I make it so that when selecting an option ( select ) of the autocomplete, I verify in the instant search by grabbing all the filled characters?.

I attach the code.

index.php

<div class="panel panel-default" style="margin-left: 15px;">
  <div>
    <table class="table" style="margin-bottom: -1px;">
  <td><div class="panel-heading"><h7>Código*</h7></div></td>
  <td><div class="panel-heading"><h7><i>Verificación</i></h7></div></td>
   </table>
    <table class="table">
  <td><center>
    <input maxlength="11" type="text" required name="codigo_pac" id="skills2" onkeyup="buscar_ajax(this.value); ">
    </center>
    <input type="text" id="busqueda" />
  </td>
  <td>
    <div id="resultado"></div>
  </td>

    </table>

  </div>
  </div>

The js script is:

<script>
$(document).ready(function(){

    var consulta;

     //hacemos focus al campo de búsqueda
    $("#skills2").focus();

    //comprobamos si se pulsa una tecla
    $("#skills2").keyup(function(e){

          //obtenemos el texto introducido en el campo de búsqueda
          consulta = $("#skills2").val();

          //hace la búsqueda

          $.ajax({
                type: "POST",
                url: "buscardetallepaciente.php",
                data: "b="+consulta,
                dataType: "html",
                beforeSend: function(){
                      //imagen de carga
                      $("#resultado").html("<p align='center'></p>");
                },
                error: function(){
                      alert("error petición ajax");
                },
                success: function(data){                                                    
                      $("#resultado").empty();
                      $("#resultado").append(data);

                }
          });


    });

});
 </script>

The finddetallepaciente.php file is:

  <?php


  $buscar = $_POST['b'];

  if(!empty($buscar)) {
        buscar($buscar);
  }

  function buscar($b) {
        $con = mysqli_connect('localhost','root', 'xxxx');
        mysqli_select_db($con,'central');

        $sql = mysqli_query($con,"SELECT * FROM persona WHERE codigo LIKE '%".$b."%'");

        $contar = mysqli_num_rows($sql);

        if($contar == 0){
              echo "No se han encontrado resultados para '<b>".$b."</b>'.";
        }else{
              while($row=mysqli_fetch_array($sql)){
                    $a = $row['nombre'];
                    $b = $row['apellido_paterno'];
                    $c = $row['apellido_materno'];

                    echo $a." ".$b." ".$c."<br /><br />";    
              }
        }
  }

  ?>

I appreciate your help in advance ...: D

    
asked by KVN20 13.07.2018 в 22:34
source

1 answer

1

jQuery autocomplete has a couple of events to modify what is seen in the list and what is the desired value.

Likewise you can pass a function to the source (data source) to have more control of the filtering:

autocomplete.source

source: function (request, response) {}

In request.term comes what to look for, response is a callback that receives the results of the search, in this case we will send it empty if there is nothing or a list of pairs value the code found and label which is how this is shown in the selector, $resultados is an empty array or with the results of the event success .

ajax.complete dentro de autocomplete.source

    complete: function (data) {
      datos = ($resultados)?$resultados.map(
        function(x){
          return {
          value: x.codigo,
          label: x.codigo +
            " - " + x.apellido_paterno +
            " " + x.apellido_materno +
            ", " + x.nombre
        };
      }):[];
      response(datos);
   }

The callback response must always be called, that is why it is in the event complete of the ajax.

In the event success we save the results in an array so we can bring more values associated with the search by registration:

ajax.success dentro de autocomplete.source

    success: function(data){
      $resultados = JSON.parse(data);
    },

What we then show when selecting an item from the list:

autocomplete.onSelect

select: function( event, ui ) {
  $codigo = ui.item.value;
  var $detalles = $resultados.find(function(x){return x.codigo==$codigo});
  $("#resultado").html(
    "Código: " + $detalles['codigo'] + "<br/>" +
    "Nombre: " + $detalles['nombre'] + "<br/>" +
    "Apellidos: " + $detalles['apellido_paterno'] +
    " " + $detalles['apellido_materno'] + "<br/>" +
    "Label Mostrado: " + ui.item.label
  );
}

Here there is no check of whether $resultados exists because if there were no results, you can not select one.

Bonus: we modify the render so that it highlights the searched string

  .data("ui-autocomplete")._renderItem = function (ul, item) {
    var newText = String(item.label).replace(
      new RegExp(this.term, "gi"),
      "<span class='ui-state-highlight'>$&</span>");
      return $("<li></li>")
      .data("item.autocomplete", item)
      .append("<div>" + newText + "</div>")
      .appendTo(ul);
    };

For this to work, the php must change a little to return a json with the data.

We change the echo for an array $resultados that we return empty ... or with the results found.

buscardetallepaciente.php

$resultados = [];
if(!empty($_POST['b'])) {

...

  while ($row = $result->fetch_array()) {
    $codigo = $row['codigo'];
    $nombre = $row['nombre'];
    $ape_pa = $row['apellido_paterno'];
    $ape_ma = $row['apellido_materno'];

    $resultados[] = [
      "codigo" => $codigo,
      "nombre" =>  $nombre,
      "apellido_paterno" =>  $ape_pa,
      "apellido_materno" =>  $ape_ma,
    ];
  }
}
echo json_encode($resultados);

It is also good to be able to show things in a way that makes it easier to choose the correct record, for this we modify the SQL a bit:

  SELECT codigo, nombre, apellido_paterno, apellido_materno
  FROM persona WHERE codigo LIKE ?
  ORDER BY apellido_paterno, apellido_materno, nombre, codigo
  LIMIT 35

We sort by Surname, Name, code and limit the results to the first 35 (a select with many elements becomes a little uncomfortable). You can return more results, sort by some field that makes more sense, etc ... see what is most convenient for the user.

Everything together would be:

// variable global para guardar los resultados
var $resultados = [];

$(function() {
  $("#skills2").autocomplete({
    source: function(request, response) {
      consulta = request.term;
      $.ajax({
        type: "POST",
        url: "buscardetallepaciente.php",
        data: "b=" + consulta,
        beforeSend: function() {
          //imagen de carga
          $("#resultado").html("");
        },
        error: function() {
          // si hay error limpiamos resultados
          $resultados = [];
          console.log("error petición ajax");
        },
        success: function(data) {
          // console.log("S:", data);
          // si hay éxito en la consulta parseamos resultados
          // éxito aquí también significa sin resultados
          $resultados = JSON.parse(data);
        },
        complete: function(data) {
          // console.log("C",data.responseText, $resultados);
          // si hay resultados mapeamos los datos correspondientes
          // value: el valor buscado
          // label: lo que se muestra para seleccionar

          datos = ($resultados) ? $resultados.map(
            function(x) {
              return {
                value: x.codigo,
                label: x.codigo +
                  " - " + x.apellido_paterno +
                  " " + x.apellido_materno +
                  ", " + x.nombre
              };
            }) : [];
          response(datos);
        }
      });
    },

    select: function( event, ui ) {
      // console.log(ui.item);
      // al seleccionar un elemento de la lista
      // recuperamos los campos extra de resultados

      $codigo = ui.item.value;
      var $detalles = $resultados.find(function(x){return x.codigo==$codigo});
      $("#resultado").html(
        "Código: " + $detalles['codigo'] + "<br/>" +
        "Nombre: " + $detalles['nombre'] + "<br/>" +
        "Apellidos: " + $detalles['apellido_paterno'] +
        " " + $detalles['apellido_materno'] + "<br/>" +
        "Label Mostrado: " + ui.item.label
      );
    },
  }).data("ui-autocomplete")._renderItem = function (ul, item) {
    var newText = String(item.label).replace(
      new RegExp(this.term, "gi"),
      "<span class='ui-state-highlight'>$&</span>");
      return $("<li></li>")
      .data("item.autocomplete", item)
      .append("<div>" + newText + "</div>")
      .appendTo(ul);
    };
});
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>autocompleit</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" />
</head>

<body>

  <div class="panel panel-default" style="margin-left: 15px;">
    <div>
      <table class="table" style="margin-bottom: -1px;">
        <td>
          <div class="panel-heading">
            <h7>Código*</h7>
          </div>
        </td>
        <td>
          <div class="panel-heading">
            <h7><i>Verificación</i></h7>
          </div>
        </td>
      </table>
      <table class="table">
        <td>
          <center>
            <input maxlength="11" type="text" required name="codigo_pac" id="skills2">
          </center>
        </td>
        <td>
          <div id="resultado"></div>
        </td>
      </table>
    </div>
  </div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

</html>

and the php, I include a function to sanitize the search via WHERE x LIKE ? :

<?php

/**
* Returns a string with backslashes before characters that need to be escaped.
* As required by MySQL and suitable for multi-byte character sets
* Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and ctrl-Z.
* In addition, the special control characters % and _ are also escaped,
* suitable for all statements, but especially suitable for 'LIKE'.
*
* @param string $string String to add slashes to
* @return $string with '\' prepended to reserved characters
*
* @author Trevor Herselman
*/
if (function_exists('mb_ereg_replace'))
{
  function mb_escape(string $string)
  {
    return mb_ereg_replace('[\x00\x0A\x0D\x1A\x22\x25\x27\x5C\x5F]', '\
source: function (request, response) {}
', $string); } } else { function mb_escape(string $string) { return preg_replace('~[\x00\x0A\x0D\x1A\x22\x25\x27\x5C\x5F]~u', '\\
    complete: function (data) {
      datos = ($resultados)?$resultados.map(
        function(x){
          return {
          value: x.codigo,
          label: x.codigo +
            " - " + x.apellido_paterno +
            " " + x.apellido_materno +
            ", " + x.nombre
        };
      }):[];
      response(datos);
   }
', $string); } } $resultados = []; if(!empty($_POST['b'])) { $con = mysqli_connect('localhost','root', 'xxxx'); mysqli_select_db($con,'central'); $param = "%".mb_escape($_POST['b'])."%"; $SQLquery = "SELECT codigo, nombre, apellido_paterno, apellido_materno FROM persona WHERE codigo LIKE ? ORDER BY apellido_paterno, apellido_materno, nombre, codigo LIMIT 35"; $stmt = $con->prepare($SQLquery); $stmt->bind_param("s", $param); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_array()) { $codigo = $row['codigo']; $nombre = $row['nombre']; $ape_pa = $row['apellido_paterno']; $ape_ma = $row['apellido_materno']; $resultados[] = [ "codigo" => $codigo, "nombre" => $nombre, "apellido_paterno" => $ape_pa, "apellido_materno" => $ape_ma, ]; } } echo json_encode($resultados);
    
answered by 14.07.2018 / 20:39
source