Autouzupełnianie w polach formularza. Odc.1.

Słowo wstępu o Autocomplete

Jak już pisałam w artykule Nadszedł czas na jQuery przyszło mi się zmagać z problemem podpowiedzi przy uzupełnianiu formularza. Oczywiście przy małej ilości danych można się pokusić o zastosowanie elementów typu <select> ale gdy w grę wchodzą podpowiedzi pochodzące z bazy danych zawierającej tysiące rekordów a w dodatku chcemy pozostawić użytkownikowi możliwość wpisania czegoś spoza tej puli danych, pozostaje nam już tylko autouzupełnianie.

Z takim właśnie przypadkiem się zetknęłam. W formularzu który przyszło mi obsłużyć były nazwy miejscowości, gmin i ulic z całej Polski. Żaden <select> by tego nie wytrzymał. Dlatego sięgnęłam po plugin Autocomplete dla JavaScriptowego frameworka jQuery

Oczywiście, żeby móc skorzystać z dobrodziejstw tego frameworka i pluginu trzeba je do swojego projektu dołączyć. To akurat najprostsze w naszym zadaniu.
Trzeba ściągnąć paczkę z pluginem Autocomplete i rozpakować w jakimś wygodnym katalogu (niech to będzie na przykład katalog ./jq-ac). W tej paczce jest już samo jQuery. Następnie w nagłówku dokumentu należy dopisać kilka linii:

<script src="./jq-ac/lib/jquery.js" type="text/javascript"></script><script src="./jq-ac/lib/jquery.dimensions.js" type="text/javascript"></script>
<script src="./jq-ac/jquery.autocomplete.js" type="text/javascript"></script>

Wpierw dołączamy arkusz stylów zdefiniowanych dla tego pluginu. Oczywiście można go modyfikować, albo stworzyć na jego wzór inny. Następnie dołączamy sam framework jQuery i dwa pliki w których zdefiniowany jest nasz plugin. I już po krzyku.

Uruchamiamy autouzupełnianie

W najprostszym przypadku sposób użycia tego pluginu jest banalny i nie powinien nastręczać problemów nikomu kto choćby odrobinę popróbował JavaScriptu. Aby wyjaśnić w czym rzecz zacznę od skonstruowania formularza:

<form action="" method="post" name="ankieta"><input id="urzadzenia" name="urzadzenia" type="text" /> 
 <input type="submit" value="Akceptuj" />
<table>
<tbody>
<tr>
<th colspan="2">Formularz z podpowiedziami</th>
</tr>
<tr>
<td>Urządzenia</td>
</tr>
</tbody>
</table>
</form>

Nic szczególnego. Jedno pole typu <input/>, przycisk <submit/> i wszystko w tabli (nie jest to szczyt elegancji), żeby było równo. Aby podłączyć podpowiedzi do pola <input/> skorzystamy z funkcji autocomplete() W tym celu w nagłówku dokumentu dopisujemy następujący skrypt:

<script type="text/javascript">// <![CDATA[
$(document).ready(
   function (){
     $("input#urzadzenia").autocomplete("jq_urzadzenia.php",{width: 200,max: 10,selectFirst: false,	cacheLength: 1});
});
// ]]></script>

W lini nr 4 tego skryptu widzimy wywołanie funkcji autocomplete() dla elementu <input/> o id=”urzadzenia”, czyli dla jedynego elementu tego typu w naszym formularzu. Oczywiście jeśli jest tylko jedne nie musimy go szukać po id, ale lepiej wyrobić sobie taki nawyk. Przecież formularz rzadko składa się z jednego okienka <input/>.

W naszym przykładzie funkcja autocomplete() przyjmuje dwa parametry. Pierwszy z nich definiuje źródło danych, drugi to opcje. O opcjach nie będę się szczegółowo rozpisywać. Nie widzę sensu przepisywania dokumentacji , coś nieco tylko wspomnę o niektórych. Bardziej istotny jest pierwszy parametr. Może to być tablica z danymi, lub jak to jest w naszym przypadku plik, który dane będzie generował dynamicznie. Do takiego skryptu metogą get przekazywany jest niejawny parametr ‚q’, którym jest string wpisany do okienka <input/>. Cała sztuka więc polega na tym, żeby odebrać tę zmienną i sprawdzić które pozycje z listy pasują do wpisanego stringu. Poniżej najprostszy skrypt z pliku jq_urzadzenia.php

<?php
$q = $_GET['q'];
if(!$q)
   return;

$dane = array('aparat','motor','rower','samochód','telefon','telewizor'); 

$i = 0;
foreach ($dane as $id => $wartosc) {
   if(preg_match('/^'.$q.'/', $wartosc)){
      echo $wartosc.PHP_EOL;
      $i++;
   }
}

if(!$i) echo "urz±dzenie spoza listy\n";

?>

Skrypt pobiera wspomniany już parametr ‚q’, jeśli z jakiegoś powodu nie ma on wartości to kończy swoje działanie. W przeciwnym razie definiuje listę pozycji podpowiedzi. W tym przykładzie oczywiście statycznie, ale nic nie stoi na przeszkodzie, żeby w tym miejscu dokonać zapytania do bazy i stworzyć dynamicznie tę tablicę. Dlaczego to ma być tablica? Bo łatwo takie dane obsłużyć.

Po zdefiniowaniu tablicy zaczyna się pętla (linie 7-12), która szuka w niej wartości zgodnych wartością przekazaną w do skryptu. Pobiera kolejne łańcuchy znaków z tablicy i sprawdza, czy zawierają one łańcuch wpisany do okienka <input/>. Ja w tym celu wykorzystuję funkcję preg_match(), która korzysta z Perlowych wyrażeń regularnych a w dodatku wymuszam (poprzez zastosowanie metaznaku ^) aby wybrana pozycja zaczynała się od zadanego ciągu. Oczywiście tak skonstruowany skrypt jest czuły na wielkość liter. Można wykorzystać funkcję strtolower() na przykład modyfikując warunek w ten sposób:

if(preg_match('/^'.strtolower($q).'/', strtolower($wartosc))){

ale należy pamiętać, że ta funkcja sprawia poważne problemy w przypadku obecności polskich znaków w stringach i bezpieczniej by było samemu napisać odpowiednią funkcję. Wartości z tablicy, które spełniają zadany warunek (oczywiście może on być skonstruowany zupełnie inaczej, a ograniczeniem są tylko nasze potrzeby i wyobraźnia) są wyświetlane za pomocą funkcji echo. Ważne jest, aby zawsze na końcu znalazł się znak nowej linii, gdyż kolejne linie będą pojawiać się w okienku podpowiedzi jako niezależne pozycje.

W zaproponowanym tu skrypcie znajduje się dodatkowo licznik pozycji pasujących do wzorca. Dodałam go po to, żeby ułatwić zadanie użytkownikowi. Ponieważ jeśli w tablicy nie znajdzie się żadna pozycja pasująca do wzorca zostanie wyświetlony komunikat odpowiedni komunikat w tym wypadku: „urządzenie spoza listy”;

I to już tyle. Jeśli chcesz możesz zobaczyć jak to działa: demo

Lada moment opublikuję kolejny odcinek w którym pokażę co jeszcze można wydusić z tego pluginu.

EDIT (lipiec 2015):
Od dnia publikacji tego tutoriala minęło kilka lat a mimo to są ludzie, którzy chcą z niego skorzystać. Niestety obawiam się, że opisany tu plugin może nie działać z nowszymi wersjami jQuery stąd problemy. Postanowiłam ułątwić ściągnięcie dokładnie tych wersji skryptów jakie zostały użyte w powyższym demo, jak również w dalszych częściach tej serii tutoriali.

jquery.js
jquery.bgiframe.min.js
jquery.autocomplete.css
jquery.autocomplete.js

65 komentarzy do wpisu „Autouzupełnianie w polach formularza. Odc.1.”

  1. A po co w pliku jq_urzadzenia.php mają być jakieś nagłówki? Przecież to widać gołym okiem, że do selecta wpada wszystko co byłoby wyświetlone w przeglądarce gdyby uruchomić jq_urzadzenia.php niezależnie.

    A jeśli w adresie jest już jakiś parametr, to moim zdaniem nie powinno mieć wpływu, ale oczywiście nie sprawdziłam.

    I co to znaczy, że nie wyświetla CI się pierwsza litera?

  2. Witam

    Mam mały problemik z pobieraniem danych z bazy, może ktoś zerknąć na kod nie wiem gdzie tkwi babol… Nie wyświetla danych natomiast jeśli umieszczę zawartość poza warunkiem if czyli echo $wartosc.PHP_EOL; podpowiedzi wyświetla ale w przypadku braku wartości w bazie nie zwraca komunikatu…. Proszę o podpowiedź bo zmęczenie daje już znać….

    = 1) {

    $select = „select Nazwa_Pelna from Kontrahenci”;
    $dane = $baza_mssql->select_query($select);

    $i = 0;
    foreach ($dane as $id2 => $wartosc2)
    {
    foreach ($wartosc2 as $id => $wartosc )
    {
    if(preg_match(‚/^’.$q.’/’, $wartosc))
    {
    echo $wartosc.PHP_EOL;
    $i++;
    }
    }
    }
    }

    if(!$i) echo „Brak w bazie”;

    unset($baza_mssql);

    ?>

  3. = 1) {
    $select = „select Nazwa_Pelna from Kontrahenci”;
    $dane = $baza_mssql->select_query($select);
    $i = 0;
    foreach ($dane as $id2 => $wartosc2) {
    foreach ($wartosc2 as $id => $wartosc ) {
    if(preg_match(‚/^’.$q.’/’, $wartosc)) {
    echo $wartosc.PHP_EOL;
    $i++;
    } } } }
    if(!$i) echo „Brak w bazie”;
    unset($baza_mssql);
    ?>

  4. A ja mam inny kłopot:

    $q = $_GET[‚q’];
    if(!$q) return;
    $queryses = „SELECT `sprawa` FROM `dane`”;
    $zubi = mysql_query($queryses);
    while($row=mysql_fetch_row($zubi )) $dane[] = $row[0];
    $i = 0;
    foreach ($dane as $id => $wartosc) {
    if(preg_match(‚/^’.$q.’/’, $wartosc)){
    echo $wartosc.PHP_EOL;
    $i++;
    }
    }

    if(!$i) echo „Adres spoza listy\n”;

    Jak widać powyżej podpiąłem się do bazy mysql i generalnie skrypt działa jednak… nie w pełni. Rekordy w bazie, które są pobierane to różnego rodzaju – slogany, sygnatury, zestawy – tekst + liczby itd… Skrypt niektóre słowa, czy zestawy znaków ładnie wyszukuje – a innych nie. Kompletnie nie wiem w czym tkwi problem. Czy słowa oddzielone spacją mogą być również wyszukane? Zgubilem się kompletnie i nie wiem gdzie szukać rozwiązania. Podam przykład:
    przykładowe wartości w tablicy „sprawa” w mysql to:

    – Zbieranie informacji
    – aktualizacja informacji
    – adhhfjklp
    – KUBEŁ S.A.
    – 34.45/23

    Jeżeli wpiszę w formularzu cyfrę 3 – wówczas ładnie podpowiada mi 34.45/23, natomiast jeżeli wpiszę literę „a” – wówczas podpowiada mi ładnie pozycję: „adhhfjklp”, ale pozycji „aktualizacja informacji” – już nie podpowada. Jeżeli wpiszę literę „z” – również nie podpowiada mi „Zbieranie informacji”… Dziwne to…

    Proszę o help jeśli to możliwe…..

  5. Możesz mi pomóc? Starałem się zrobić wszystko jak należy

    1.

    2. załączenie jquery….

    $(document).ready(
    function (){
    $(„input#miejsceur”).autocomplete(„miasta.php”,
    {width: 200,max: 10,selectFirst: false, cacheLength: 1});
    }
    );

    3. miasta.php
    configfile….
    db= hasło itp

    $q = $_GET[‚q’];
    if(!$q) return;

    $miejsca = mysql_query(„SELECT `nazwa` FROM `miejsca` WHERE `nazwa` AS ‚$q%'”, $db);
    while($linia = mysql_fetch_array($miejsca))
    {
    $miejsce=$linia[‚nazwa’];
    echo $miejsce;
    }

    Niestety brak jest aktywności jakiejkolwiek. Gdy na końcu miasta.php dopisuję
    echo json_encode($miejsce);
    otrzymuję listę z jedną pozycją: null

    UWAGA: adres strony głównej jest ze zmiennymi index.php?akcja=cośtam

  6. Jesteś pewien, że masz prawidłowe zapytanie? Na początek zamiast tej sekcji z zapytaniem do bazy przygotuj po prostu na sztywno tablice i zobacz, czy wtedy będzie się wyświetlało. Jeśli tak, to znaczy że zapytanie zwraca null. I jeszcze. Uruchom sam plik miasta.php i zobacz co wyświetla.

  7. po próbach udało się – teraz działa (ale nie wiem czy to dobrze napisane) – wychodzi chyba na to że nie było wcześniejszej definicji zmiennej „$miejsce” (dolny cudzysłów przy SELCT się zrobił tutaj przypadkiem)

    if(!empty($_GET[‚q’])) {

    $q = $_GET[‚q’];
    $query=mysql_query(„SELECT nazwa FROM miejsca WHERE nazwa LIKE ‚%$q%'”, $db);

    while($row = mysql_fetch_array($query)){

    $data=”;
    $data=$row[‚nazwa’];
    echo $data.”\n”;
    }
    }

    niestety – okazuje się, że muszę mieć bardziej skomplikowany skrypt. Z tabeli „miejsca” muszę podczas wpisywania nazwy pobrać wartości trzech kolumn i rozdzielić je na trzy inputy (ukryty numer, nazwa i opis). Konfiguracja skryptu jq mnie przerosła. Może mógłby prosić o jakąś pomoc?

  8. Witam. Minął rok od ostatniego posta, ale mam nadzieję, że autorka to przeczyta. Po pierwsze dziękuję za poradniki. Super sprawa. Ale chyba robię coś źle i niestety nie działa mi to autouzupełnianie. Po wpisaniu słowa z tablicy nic się nie dzieje. Być może kwestia problemów z pluginami, do których linki już nie działają. Proszę o pomoc.

Dodaj komentarz

%d bloggers like this: