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:
- <link rel="stylesheet" href="./jq-ac/jquery.autocomplete.css" type="text/css" />
- <script type="text/javascript" src="./jq-ac/lib/jquery.js"></script>
- <script type="text/javascript" src="./jq-ac/lib/jquery.dimensions.js"></script>
- <script type="text/javascript" src="./jq-ac/jquery.autocomplete.js"></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:
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">
- $(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;
- $i = 0;
- foreach ($dane as $id => $wartosc) {
- echo $wartosc.PHP_EOL;
- $i++;
- }
- }
- ?>
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:
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.
11 paź 2008 o 11:30
Ciekawa opcja

Nie myślałem, że przez jQuery można coś takiego stworzyć
Dzięki za wpis
14 paź 2008 o 12:42
Oj można jeszcze więcej. Zobaczysz w drugim odcinku
16 lis 2008 o 22:35
Witam
Niestety nie mogę sobie poradzić z pobraniem danych z bazy mysql
robie to w następujący sposób:
while($dane = mysql_fetch_array($wynik))
17 lis 2008 o 11:01
Przyślij mi na e-mail cały kod w którym pobierasz dane i przygotowujesz je do autouzupełniania. Spróbuję rzucić okiem.
17 kwi 2009 o 13:10
Ciekawy artykuł, oby więcej takich
1 sie 2009 o 20:39
Witam Panią bardzo fajnie to Pani pokazała na przykładzie a ja szukałem autouzupełnienia i proszę tu tak przyjaźnie napisane. Mam też i pytanie do Pani, w przykładzie pokazuje Pani autouzupełnianie na przykładzie danych wprowadzonych ręcznie do skryptu: „jq_urzadzenia.php” moje pytanie brzmi czy mogła by Pani pokazać jak np pobierać dane do autouzupełnienia z bazy danych i to np określone dane z określonych tabel to by było ciekawe bo np jakbyśmy chcieli zrobić taki trik dla kodów pocztowych albo miejscowości to wpisywanie ręcznie wszystkich tych danych do skryptu php było by koszmarem. Pozdrawiam serdecznie
1 sie 2009 o 21:05
To nic skomplikowanego. Zamiast:
$dane = array(‘aparat’,'motor’,'rower’,'samochód’,'telefon’,'telewizor’);
trzeba napisać:
$dane = moja_funkcja();
No i gdzieś trzeba tę funkcję zdefiniować tak, żeby zwracała tablicę.
Oczywiście tablica kodów pocztowych byłaby koszmarnie długa. Są sposoby, aby pobierać tylko potrzebną część danych. Może faktycznie pokuszę się o stosowny tutorial.
1 kwi 2010 o 10:52
Witam,
szkoda, że tak późno tutaj trafiłem
W sumie przerobiłem skrypt aby pobierał informacje z bazy (MSSQL). Walczę teraz z kodowaniem
Niestety mam krzaczki.. problem rozwiązuje częściowo:
header(‘Content-Type: text/html; charset=windows-1250′);
Częściowo ponieważ nie wyszukuje słów rozpoczynających się polskimi literami.. natomiast jak polska litera jest druga i kolejna to nie ma problemu. Przykład:
maść -> i jest ok, prawidłowo sugeruje, prawidłowo rozpoznaje ść, wpisując maść widzi pl znaki
natomiast słowo:
ściana -> nie znajduje, nie daje żadnej sugestii do słów rozpoczynających się od polskich znaków śćźłż itd..
Ma Pani jakiś pomysł na to?
Dziękuję i pozdrawiam !
1 kwi 2010 o 23:00
Ałć… A czemu stosujesz 1250? A feee.
A czytałeś mój artykuł opolskich znakach w php? http://blog.bexlab.pl/polskie-znaki-w-php-dramat-w-czterech-aktach/65/
2 kwi 2010 o 8:59
Aha, czytałem
Bazę MSSQL mam w Polish_CI_AS a strona kodowa dla tej kolacji to 1250. Wracając to mojego pytania -> problem nareszcie rozwiązałem. POST a nie GET
Oto całe rozwiązanie
15 maj 2010 o 17:49
Przepisałem dosłownie cały kod zmieniając tylko nazwę inputa, ścieżki do js i danych (gotowa tabelka w js generowana phpem)
wpisuję:
$(document).ready(
function (){
$(„input#lista_osob”).autocomplete(„osoby”,
{width: 200,max: 10,selectFirst: false, cacheLength: 1});
}
);
i za każdym razem Firebug wypisuje mi: ‘autocomplete is not a function’
15 maj 2010 o 18:05
A co to jest „osoby”?
15 maj 2010 o 18:11
nazwa tabeli
wycinek:
var osoby = [
{id:"00136", imie:"Anna"},
{id:"00145", imie:"Adam"},
{id:"00118", imie:"Zygmunt"},
]
15 maj 2010 o 19:00
Może problem tkwi w deklaracji tej tablicy? A czy to nie powinno być bez cudzysłowa?
15 maj 2010 o 19:10
w przykładach http://jquery.bassistance.de/autocomplete/demo/ był taki kod, ale nie za bardzo go rozumiem zwłaszcz formatItem :
$(„#thickboxEmail”).autocomplete(emails, {
minChars: 0,
width: 310,
matchContains: true,
highlightItem: false,
formatItem: function(row, i, max, term) {
return row.name.replace(new RegExp(„(” + term + „)”, „gi”), „$1„) + „Email: <” + row.to + „>”;
},
formatResult: function(row) {
return row.to;
}
});
polami w tabeli emails były ‘to’ i ‘name’
15 maj 2010 o 19:28
Na temat formatItem naskrobię w wolnej chwili, ale tymczasem zwróć uwagę, że nazwę tablicy wstawia się bez cudzysłowu.
16 maj 2010 o 11:52
Kombinowałem już na wszelkie możliwe sposoby i nadal nic, a w dodatku muszę to mieć do wieczora :/ Może jest ktoś w stanie mi wyjaśnić gdzie mam błąd? (Uwaga strona stoi na powolnym serwerze)
http://czacki.edu.pl/~janusz/af_test/panel_af/panel_af.php?czynnosc=dodawanie&tabela=rel_os_przedst_poz&zakl=baza&krok=1
16 maj 2010 o 15:15
Odkryłem co było nie tak. Dwa razy wrzucałem samo jQuery.
12 sty 2011 o 15:31
Te pierwsze trzy kody od góry mają sie znależć w jednym pliku index.php?
Bo nie bardzo wiem gdzie mam te poszczególen bloki kodu wpisać. prosze o pomoc
12 sty 2011 o 15:55
Formularz ma się znaleźć na tej stronie na której chcesz mieć formularz
a skrypty powinny być na tej samej stronie tylko w sekcji <head>
8 kwi 2011 o 16:58
Witam,
Odnośnie Pani wpisu : To nic skomplikowanego. Zamiast:
$dane = array(‘aparat’,’motor’,’rower’,’samochód’,’telefon’,’telewizor’);
trzeba napisać:
$dane = moja_funkcja();
No i gdzieś trzeba tę funkcję zdefiniować tak, żeby zwracała tablicę
Czy mogę prosić o wskazówki
Pozdrawiam
8 kwi 2011 o 21:13
A nie ma ich w następnych artykułach?
10 kwi 2011 o 19:01
Witam, Niestety nie znalazłem w następnych artykułach. Chodzi mi o dopisanie funkcji pobierającej dane z bazy i nie wiem jak się do tego zabrać
10 kwi 2011 o 23:06
No rzeczywiście. Dawno już pisałam te artykuły i nie pamiętałam co tam dalej było.
To naprawdę proste. Zamiast linijki
$dane = array(‘aparat’,'motor’,'rower’,'samochód’,'telefon’,'telewizor’);
Trzeba wstawić wywołanie skryptu, który pobierze dane z bazy i zwróci stosowną tablicę. Definiujesz sobie taki skrypt, w którym będzie funkcja potrafiąca połączyć się z bazą (mysql_connect), wykonać na niej zapytanie SQL (mysql_query) i przetworzyć je do postaci potrzebnej tablicy (mysql_fetch_row). Skrypt dołączasz za pomocą include i już. Prawdę mówiąc nie bardzo rozumiem z czym masz problem. Może więcej napiszesz?
11 kwi 2011 o 15:07
Ok, zrobię tak jak napisałaś i dam znać ( raczkuję w php i może stąd banalny problem )
12 kwi 2011 o 15:43
Zamiast – $dane = array(‘aparat’,’motor’,’rower’,’samochód’,’telefon’,’telewizor’);
wstawiłem :include ‘connect.php’;
include ‘query.php’;
a moje query wygląda tak :
Niby ok , ale tylko pokazuje pierwszą wartość z bazy
12 kwi 2011 o 15:43
query :
$zapytanie = „SELECT id FROM adres”;
$wynik = mysql_query($zapytanie);
$dane = mysql_fetch_row($wynik);
12 kwi 2011 o 20:57
Bo linijka $dane = mysql_fetch_row($wynik); bierze tylko pierwszy rekord. Trzeba to zrobić w petli tak jak w manualu pokazują:
http://pl2.php.net/manual/en/function.mysql-fetch-row.php#81309
Czyli:
while($row=mysql_fetch_array($wynik ))
$dane[] = $row['id'];
while($row=mysql_fetch_row($wynik )) $dane[] = $row[0];
13 kwi 2011 o 0:31
Dziekuje – jest ok
18 cze 2011 o 15:40
A u mnie skrypt php wcale nie otrzymuje parametru. Gdy dodam jakąś zmienną $q w środku skryptu to pokazuje tylko pasujące do niej podpowiedzi, a parametru nie widzi.
25 cze 2011 o 22:55
Nie sądzę, żeby nie znając kodu, udało mi się zgadnąć, dlaczego tak się dzieje.
19 sie 2011 o 20:38
Mam pytanko, może laickie ale i tak je zadam. Skoro tak się udało rozpisać o tablicach to może gotowy przykładzik na bazę? Ten tu podany zawiera tylko fragment rozsiany, a tak jak to tu było zaznaczone, bardziej się przyda przykład z bazą zawierającą tysiące rekordów niż z tablicą która ma ich kilka. Czy byłaby taka możliwość by załączyć kompletny skrypt na bazę? Za cierpliwość w nadmiarze z góry dziękuję
27 sie 2011 o 23:08
No nie żartuj. Przecież nawiązanie połączenia z bazą, wysłanie zapytania, odebranie rekordów i wrzucenie ich w pętli do tablicy to szkolne zadanie. Znajdziesz to w każdym podręczniku do PHP. A podpowiedzi sa w starszych komentarzach. Gotowca nie będę pisać. To by było mało wychowawcze, a ja mam belferską naturę
8 lis 2011 o 16:12
Kłopot mam w tym, że zakładając, iż tabela ma dwa rekordy: id, nazwisko – chciałbym z inputa odebrać id (pomimo, że uzupełniane nazwisko), i tu mam zonka. Jak z tego odebrać zmienną? Starałem się dodać tą zmienną w zapytaniu do bazy ale poległem. Pomijając fakt, że przy Polskich ogonkach najczęściej zaprezentowany skrypt omija te rekordy. Czy na prawdę nie da się tego jakoś obejść. Heh skoro belferska natura – to pytam
8 lis 2011 o 17:21
I bardzo dobrze, że pytasz. Lubie dociekliwych studentów, nawet jeśli są niecierpliwi
Sądzę, że podpowiedź w związku z pierwszym pytaniem znajdziesz w drugim odcinku tej serii:
http://blog.bexlab.pl/autouzupelnianie/62/
Natomiast jeśli chodzi o polskie znaki, to tez się trochę z tym zmagałam i to co odkryłam opisałam tu:
http://blog.bexlab.pl/polskie-znaki-w-php-dramat-w-czterech-aktach/65/
Życzę przyjemnej lektury.
30 lis 2011 o 22:22
A ja mam niezłą zagwozdkę, bo chciałbym połączyć autouzupełnianie z dynamicznie generowanymi polami formularza z tej strony http://antczak.org/2009/10/dynamiczne-formularze-z-uzyciem-jquery/ , ale nie mam pomysłu na id.
1 gru 2011 o 10:36
Ale to co? Mamy Ci wymyślić jakie masz nadać ID?
1 gru 2011 o 16:38
W twoim przykładzie id jest przypisane na stałe, a co w przypadku gdy id jest generowane dynamicznie, i nie mogę użyć $(„input#urzadzenia”)
2 gru 2011 o 11:57
To wtedy trzeba pokombinować. Nie sprawdziłam, ale spróbowałabym najpierw wykryć który element został kliknięty, odczytać jego ID a następnie zastosować do niego funkcję autocomplete.
2 gru 2011 o 22:03
No i pokombinowałem i bardzo obszerny artykuł na temat autouzupełniania, poszerzający to co jest zawarte tutaj można znaleźć pod adresem http://dev.baczyk.net/2009/12/24/jquery-autocomplete-magiczne-podpowiedzi/