Home » Php » php – How to create multiple autocomplete in an input field based on a sentence structure?

php – How to create multiple autocomplete in an input field based on a sentence structure?

Posted by: admin July 12, 2020 Leave a comment

Questions:

The sentence structure of my autocomplete is:

<Occupation> <for> <time period>

Example:

  • Student for 5 years
  • Teacher for 2 years

In the database, I have a column containing a list of occupations. With jQuery UI autocomplete, I populate the first two sections in the text input using the following codes:

<script>
    $(function() {
        $("#occupation").autocomplete({
            source: 'search.php',
            delay: 500,
            select: function(event, ui) {
                $(this).val(ui.item.value)
            }
        });
    });
</script>
<input type='text' name='occupation' id='occupation’>

The search.php code:

<?php
$searchTerm = $_GET['term'];
$query = $db->query("SELECT DISTINCT occupation FROM table WHERE occupation LIKE '%" . $searchTerm . "%' ORDER BY occupation ASC");
$a_json = array();

while ($row = $query->fetch_assoc())
    {
    $data_row["value"] = $row['occupation'] . ' for';
    $data_row["label"] = $row['occupation'];
    array_push($a_json, $data_row);
    }

echo json_encode($a_json);

Now, is there any way to create a second trigger to make an autocomplete for the rest? Like after selecting an occupation, if the user inputs 5, it’ll show the following autocomplete options for the time period: 5 days/ 5 weeks/ 5 months/ 5 years. Like the image below:
Example

Thanks in advance for your suggestions.

How to&Answers:

I would advise following the Multiple example shown here: http://jqueryui.com/autocomplete/#multiple

Basically, we’re going to selectively pick out tags to fill in, using " for" as your delimiter instead of ",".

var occupations = [{
  value: "Assistant for",
  label: "Assistant"
}, {
  value: "Student for",
  label: "Student"
}, {
  value: "Teacher for",
  label: "Teacher"
}];

var oLength = [
  "Days",
  "Weeks",
  "Months",
  "Years"
];

$(function() {
  function split(val) {
    return val.split(/\sfor/);
  }

  function extractLast(term) {
    return split(term).pop();
  }

  $("#occupation").on("keydown", function(event) {
    if (event.keyCode === $.ui.keyCode.TAB &&
      $(this).autocomplete("instance").menu.active) {
      event.preventDefault();
    }
  }).autocomplete({
    minLength: 0,
    source: function(request, response) {
      var term = extractLast(request.term);
      var results = [];
      if (request.term.indexOf("for") > 0) {
        var regE = /^(.*)\sfor\s(\d)\s(.*)$/
        if (regE.test(request.term)) {
          return false;
        }
        if (parseInt(term) > 0) {
          $.each(oLength, function(k, v) {
            results.push(term + " " + v);
          });
        }
      } else {
        results = $.ui.autocomplete.filter(
          occupations, request.term);
      }
      response(results);
    },
    focus: function() {
      // prevent value inserted on focus
      return false;
    },
    select: function(event, ui) {
      var terms = split(this.value);
      terms[0] = terms[0] + " for";
      // remove the current input
      terms.pop();
      // add the selected item
      terms.push(ui.item.value);
      // add placeholder to get the comma-and-space at the end
      terms.push("");
      this.value = terms.join("");
      return false;
    }
  });
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<input type="text" id="occupation" />

Answer:

You can parse the query, when you have a number (as we don’t have words with numbers yet) you could make the call to autocomplete again.

Example:

$number = preg_replace('/\D/', '', $query); // replaces every non number for empty string
if (is_numeric($number))
{
    $output = '';
    // return variations like you want
    foreach (array ('weeks', 'years') as $period)
    {
        $output .= $number . $period;
    }
    return $output;
}

Answer:

You need to tokenize your input.
Your structure requires four tokens: <Occupation>, <for>, <time length> and <time unit>.
You need to check for the presence of the <for> token.

  • When you start writing the <Occupation> token, your code will search and fetch back choices for occupations. When you select one, you will fill the input with the “<Occupation> <for>” sentence.
  • If you click again on it, you must check if the second token is <for>.
    • If it is there, then you will not focus on showing occupations but possible time periods.
    • If you have a number in the third token, then you will need to show only time units. If you don’t, then show some sample combinations like “2 days”, “5 months”, “1 year”.

This can be done easily with Javascript.

Answer:

Provided the list isn’t in the millions of records, why not simply move some of the database into the client by using localStorage or indexedDB ? that would probably help with the user experience.