0

Lately I have been trying to code a system where a php file reads a text file that is full of names(right now I just put john doe) and displays it as autocomplete text. here is what I have tried in html:

function showHint(str) {
  var xhttp;
  if (str.length == 0) { 
    document.getElementById("txtHint").innerHTML = "";
    return;
  }
  xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
      document.getElementById("txtHint").innerHTML = xhttp.responseText;
    }
  };
  xhttp.open("GET", "gethint.php?q="+str, true);
  xhttp.send();   
}
<!DOCTYPE html>
<html>
<body>

<h3>Start typing a name in the input field below:</h3>

<form action=""> 
First name: <input type="text" id="txt1" onkeyup="showHint(this.value)">
</form>

<p>Suggestions: <span id="txtHint"></span></p> 
  </body>
  </html>

here is gethint.php, the part that dosent work,

<?php
// Array with names
$a = fopen("data.txt", "r") or die("Unable to open file!");
echo fread($a,filesize("data.txt"));
fclose($a);

// get the q parameter from URL
$q = $_REQUEST["q"];

$hint = "";

// lookup all hints from array if $q is different from "" 
if ($q !== "") {
    $q = strtolower($q);
    $len=strlen($q);
    foreach($a as $name) {
        if (stristr($q, substr($name, 0, $len))) {
            if ($hint === "") {
                $hint = $name;
            } else {
                $hint .= ", $name";
            }
        }
    }
}

// Output "no suggestion" if no hint was found or output correct values 
echo $hint === "" ? "no suggestion" : $hint;
?>
parseguy
  • 129
  • 2
  • 17

2 Answers2

0

You could do it like:

$q = $_REQUEST["q"];

//Read file contents as an array
$lines = file("data.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

//Default output
$suggestions = "No suggestions...";

//If the  file is not empty, try to search lines that contains $q
if(!empty($lines)){

    //Search for $q inside a line, case insensitive
    $results = array_filter($lines, function($line){
        return stripos($line, $q) !== false;
    });
    $suggestions = implode(", ", $results);
}

//Output
echo $suggestions;
CarlosCarucce
  • 3,420
  • 1
  • 28
  • 51
  • Why should the OP try this? A ***good answer*** will always have an explanation of what was done and why it was done that way, not only for the OP but for future visitors to SO. – Jay Blanchard Jan 25 '16 at 13:31
  • ...plus that this answer will show the full content of the file every time, regardless of the input. – M. Eriksson Jan 25 '16 at 13:33
  • I've updated my answer, with some comments... hope i made it a bit more clear – CarlosCarucce Jan 25 '16 at 13:44
0

If it's possible, I would store the names in a decent format, such as JSON:

data.json:

["Nav", "bob", "John"]

Then loading the names in would be easy:

gethint.php

 $names = json_decode(file_get_contents('data.json'), true);
 $output = array();
 $q = $_REQUEST["q"]

foreach($names as $name) {
  if ($name == $q) {
    $output[] = $name
  }
}

// output the results as JSON
echo json_encode($output);

Then you could use JSON.parse() to parse the JSON in your JS and do whatever with it:

function showHint(str) {
  var xhttp;
  if (str.length == 0) { 
    document.getElementById("txtHint").innerHTML = "";
    return;
  }
  xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
      var results = JSON.parse(xhttp.responseText);
      // Do whatever with results
    }
  };
  xhttp.open("GET", "gethint.php?q="+str, true);
  xhttp.send();   
}
navnav
  • 204
  • 2
  • 9
  • Too be totally honest, you're not gaining anything by using JSON instead of a file with one name on each row. It does add an extra step parsing the JSON, though. And your solution will only show suggestions if the input is an exact match, not partial matches. – M. Eriksson Jan 25 '16 at 13:40
  • @MagnusEriksson Using plain text would be fine, if we were still in the 20th century. JSON is neater. @OP if you'd like to do partial searches instead of just exact matches, use `strstr()`. The purpose of my answer was not to write the OP's code for him/her, just to give them an example. – navnav Jan 25 '16 at 13:45
  • "Is neater"... good argument for adding unnecessary complexity. Regardless of the century, you should always follow KISS (https://en.wikipedia.org/wiki/KISS_principle). The OP needs a list of names. No other properties. Using JSON in this specific case will 1. add one extra parsing step which does affect performance and 2. make the file bigger (since you need to add extra markup in the file). What do you gain? It's being a bit "neater"? – M. Eriksson Jan 25 '16 at 13:54