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
i co jeśli w adresie jest juz jakis parametr $_Get. Mi dziala tylko na stronie głównej.
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?
No właśnie majac w adresie np http://strona.pl?go=1 nie chce działać. Idzie tylko z http://strona.pl :( . Nie wiesz gdzie może być przyczyna?? Już nie mam pomysłów. Z góry dziękuję dodałem bloga do ulubionych , dobra robota :).
A czy jest możliwość włączenia auto uzupełniania w wordpress theme ala ten http://wp.contempographicdesign.com/wp_real_estate_4/ ?
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);
?>
= 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);
?>
już znalazłem o co chodzi….. zresztą było o tym pisane małe i duże litery…. Wychodzi zmęczenie….
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…..
A spróbuj po wczytaniu z bazy tekstów zamienić spacje na encje albo na %20
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
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.
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?
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.
A czy jesteś pewien, że to jest ta sama wersja pluginu?