GAJDAW


MOJE KSIĄŻKI

Książka pt. Git. Recipes
Książka pt. Git. Rozproszony system kontroli wersji
Książka pt. PhpStorm Starter
Książka pt. Symfony w przykładach
Książka pt. GIMP. Praktyczne projekty. Wydanie II
Książka pt. PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych
Książka pt. PHP. Praktyczne projekty

PROGRAMY

Słownik z autouzupełnianiem przy użyciu jQuery

Włodzimierz Gajda

Artykuł omawia słownik angielsko-angielski z autouzupełnianiem. Podane rozwiązanie wykorzystuje jQuery. Jeden z omówionych przykładów stosuje pliki tekstowe, a drugi — bazę danych.

1. Działanie słownika

Słownik zawiera pole input do wprowadzania wyrazów (rysunek 1).

Rysunek 1. Strona główna przykładu: skrypt slownik.php

Po wprowadzeniu słowa 'dea' pojawia się lista z podpowiedziami. Lista zawiera wszystkie słowa zawarte w słowniku, które rozpoczynają się od liter 'dea' (rysunek 2).

Rysunek 2. Lista podpowiedzi

Po wybraniu z listy słowa 'deaconhood' jego wyjaśnienie pojawia się na stronie bez zatwierdzania formularza (rysunek 3).

Lista podpowiedzi z rysunku 2 oraz wyjaśnienie słowa z rysunku 3 są pobierane w tle, bez przeładowania strony.

Rysunek 3. Po wybraniu podpowiedzi z listy pod formularzem pojawia się wyjaśnienie wybranego słowa

2. Implementacja słownika w oparciu o pliki tekstowe

2.1 Dane

Słownik w formacie tekstowym jest zapisany w folderze dane/. Składa się on z pliku dictionary.txt oraz plików w folderze dane/words/.

Plik dictionary.txt zawiera listę wszystkich słów zawartych w słowniku, np.:

d
dab
dabb
dabber
dabble
dabbler
dabblingly
dabchick
...

Wyjaśnienie każdego ze słów jest zawarte w osobnym pliku tekstowym, np.:

dane/words/d.txt
dane/words/dab.txt
dane/words/dabb.txt
dane/words/dabber.txt
dane/words/dabble.txt
dane/words/dabbler.txt
dane/words/dabblingly.txt
dane/words/dabchick.txt
...

Pliki z wyjaśnieniem słów są w formacie HTML:

<p><strong class="hw">Dan"i*el</strong><br /> (?),
<span class="pos"><i>n.</i></span> <span class="def">A Hebrew prophet
distinguished for sagacity and ripeness of judgment in youth; hence,
a sagacious and upright judge.</span></p>

...

Jest to nieco zmodyfikowany format stosowany w słowniku Webstera, który jest dostępny na stronie http://www.gutenberg.org/etext/662.

3. Skrypty składające się na rozwiązanie

Słownik z podpowiedziami składa się z trzech skryptów:

Pierwszy z nich, podaj-wyrazy.php, zwraca listę słów, które są umieszczane na liście podpowiedzi z rysunku 2.

Drugi, podaj-wyjasnienie.php, zwraca wyjaśnienie słowa umieszczane pod formularzem (rysunek 3).

Trzeci, slownik.php, zawiera formularz oraz implementację interakcji z użytkownikiem.

3.1 Skrypt podaj-wyrazy.php

Skrypt podaj-wyrazy.php został przedstawiony na listingu 1.

Skrypt ten wykorzystuje dwie zmienne URL:

$_GET['limit']
$_GET['q']

Przykładowe wywołanie skryptu może mieć postać:

podaj-wyrazy.php?q=deta&limit=13

Wywołanie to zwróci pierwsze trzynaście wyrazów rozpoczynających się od liter 'deta'.

Jeśli zmienna limit nie jest podana, to zwracane są wszystkie słowa o danym prefiksie.

Jeśli nie podamy zmiennej q, to wynikiem będzie pełna lista słów ze słownika.

Skrypt ten wykorzystuje plik dane/dictionary.txt.

require_once 'walidacja.inc.php';

$p = file('dane/dictionary.txt');
$pc = count($p);

if (isset($_GET['limit']) && str_ievpi($_GET['limit'])) {

    $maks = $_GET['limit'];

} else {

    $maks = $pc;
    
}


if (isset($_GET['q']) && (preg_match('/^[a-z]+$/i', $_GET['q']))) {

    $wynik = array();
    
    for (
        $i = 0, $liczba_elementow = 0;
        ($liczba_elementow < $maks) && ($i < $pc);
	$i++
    ) {
        if (strpos($p[$i], $_GET['q']) === 0) {
            $wynik[] = $p[$i];
            $liczba_elementow++;
        };

    }


} else {

    $wynik = array_slice($p, 0, $maks);    
    
}

echo implode('', $wynik);

Listing 1. Pliki tekstowe — skrypt podaj-wyrazy.php

3.2 Skrypt podaj-wyjasnienie.php

Skrypt podaj-wyjasnienie.php wykorzystuje jedną zmienną URL:

$_GET['word']

Jego zadaniem jest wydrukowanie zawartości pliku tekstowego zawierającego wyjaśnienie wybranego słowa. Po wpisaniu adresu:

podaj-wyjasnienie.php?word=detinue

skrypt zwróci zawartość pliku tekstowego dane/words/detinue.txt, czyli wyjaśnienie słowa detinue.

Treść skryptu jest przedstawiona na listingu 2.

if (
    isset($_GET['word']) && 
    preg_match('/^[a-ząćęłńóśźż]+$/ui', $_GET['word']) 
    && file_exists('dane/words/' . $_GET['word'] . '.txt')
) {

    readfile('dane/words/' . $_GET['word'] . '.txt');
    
} else {
    echo 'brak';
}

Listing 2. Pliki tekstowe — skrypt podaj-wyjasnienie.php

Funkcja readfile() odczytuje i wysyła plik.

Wywołanie:

readfile('p.txt');

jest równoważne:

echo file_get_contents('p.txt');

3.3 Skrypt slownik.php

Skrypt slownik.php jest przedstawiony na listingu 3. Zawiera on znaczniki dołączające bibliotekę jQuery:

<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript" src="lib/jquery.bgiframe.min.js"></script>
<script type="text/javascript" src="lib/jquery.ajaxQueue.js"></script>
<script type="text/javascript" src="lib/thickbox-compressed.js"></script>
<script type="text/javascript" src="lib/jquery.autocomplete.js"></script>
<link rel="stylesheet" type="text/css" href="lib/jquery.autocomplete.css" />
<link rel="stylesheet" type="text/css" href="lib/thickbox.css" />

implementację autouzupełniania w jQuery:

$(function() {

    $('#explanation').hide();

    $("#input_wyraz").autocomplete("podaj-wyrazy.php", {
            scroll: true
    });

    $('form').submit(function(){
        $('#explanation').load('podaj-wyjasnienie.php?word=' + 
	    $('#input_wyraz').attr('value'));                
        $('#explanation').show();
        return false;
    });              

    $("#input_wyraz").result(function(){

        $('#explanation').load('podaj-wyjasnienie.php?word=' + 
	    $('#input_wyraz').attr('value'));                	
        $('#explanation').show();            
    });

});

formularz:

<form action="slownik.php" method="get">
    <p>
        <label>Wyraz:</label>
        <input type="text" id="input_wyraz" name="word" />
        <input type="submit" value="Wyślij" />
    </p>
</form>

oraz kod obsługujący przeładowanie formularza:

<div id="explanation">
<?php

include('podaj-wyjasnienie.php');

?>
</div>

Rozwiązanie Ajaksowe będzie działało nawet wtedy, element div#explanation pozostawimy pusty:

<div id="explanation"></div>

Jeśli jednak chcemy, by rozwiązanie działało także przy wyłączonej obsłudze JavaScript, to należy dodać kod PHP wykonywany po przeładowaniu formularza. Najprościej wykonać to wykorzystując gotowy już skrypt podaj-wyjasnienie.php. Formularz stosuje metodę get, zaś element input ma nazwę word. Dzięki temu wewnątrz elementu div#explanation wystarczy dołączyć skrypt podaj-wyjasnienie.php:

include('podaj-wyjasnienie.php');
<!DOCTYPE...>
<html>
    ...
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="lib/jquery.js"></script>
    <script type="text/javascript" src="lib/jquery.bgiframe.min.js"></script>
    <script type="text/javascript" src="lib/jquery.ajaxQueue.js"></script>
    <script type="text/javascript" src="lib/thickbox-compressed.js"></script>
    <script type="text/javascript" src="lib/jquery.autocomplete.js"></script>
    <link rel="stylesheet" type="text/css" href="lib/jquery.autocomplete.css" />
    <link rel="stylesheet" type="text/css" href="lib/thickbox.css" />
    
    <script type="text/javascript">
    $(function() {
    
        $('#explanation').hide();

        $("#input_wyraz").autocomplete("podaj-wyrazy.php", {
            scroll: true
        });
        
        $('form').submit(function(){
            $('#explanation').load('podaj-wyjasnienie.php?word=' + 
	        $('#input_wyraz').attr('value'));                
            $('#explanation').show();
            return false;
        });              
        
	$("#input_wyraz").result(function(){

            $('#explanation').load('podaj-wyjasnienie.php?word=' + 
	        $('#input_wyraz').attr('value'));                	
            $('#explanation').show();            
	});

    });
    </script>
    
  </head>
<body>

<div>
    <form action="slownik.php" method="get">
        <p>
            <label>Wyraz:</label>
            <input type="text" id="input_wyraz" name="word" />
            <input type="submit" value="Wyślij" />
        </p>
    </form>
</div>

<div id="explanation">
<?php

include('podaj-wyjasnienie.php');

?>
</div>

</body>
</html>

Listing 3. Pliki tekstowe — skrypt slownik.php

4. Implementacja słownika w oparciu o bazę danych

Rozwiązanie tak jak poprzednio składa się z trzech plików:

Skrypt slownik.php jest identyczny jak poprzednio. Zmianie ulegają wyłącznie pliki podaj-wyrazy.php oraz podaj-wyjasnienie.php.

4.1 Baza danych i aktywne rekordy

Najpierw projektujemy bazę danych przedstawioną na rysunku 4 oraz generujemy obiekty Propel-a.

Rysunek 4. Model bazy danych

Następnie wypełniamy bazę danych rekordami. Zadanie to wykonuje skrypt parse.php. Został on przetestowany na pliku ze słownikiem Webstera, hasła na literę D oraz E.

4.2 Skrypt podaj-wyrazy.php wykorzystujący bazę danych

Skrypt podaj-wyrazy.php, który wykorzystuje bazę danych rozpoczyna się od inicjalizacji obiektów Propel-a:

require_once 'propel/Propel.php';
require_once 'dictionary/Word.php';

Propel::init('dictionary-conf.php');

Następnie tworzymy nowe kryteria wyszukiwania, które będą zwracały wyrazy posortowane alfabetycznie:

$c = new Criteria;
$c->addAscendingOrderByColumn(WordPeer::HEADWORD);

Jeśli jest podana zmienna $_GET['limit'] to w kryteriach ustalamy limit liczby zwracanych rekordów:

if (isset($_GET['limit']) && str_ievpi($_GET['limit'])) {

    $c->setLimit($_GET['limit']);

};

Ostatnie kryterium wyszukiwania odpowiada za pobranie z bazy danych tylko słów o zadanym przedrostku:

if (isset($_GET['q']) && (preg_match('/^[a-z]+$/ui', $_GET['q']))) {

    $c->add(WordPeer::HEADWORD, $_GET['q'] . '%', Criteria::LIKE);

}

Po ustaleniu kryteriów pobieramy rekordy z bazy danych:

$slowa = WordPeer::doSelect($c);

po czym przetwarzamy w pętli, drukując słowa:

foreach ($slowa as $s) {
    echo $s->getHeadword() . "\r\n";
}

Listing 4 przedstawia kompletny skrypt podaj-wyrazy.php wykorzystujący bazę danych.

require_once 'propel/Propel.php';
require_once 'dictionary/Word.php';

Propel::init('dictionary-conf.php');

require_once 'walidacja.inc.php';

$c = new Criteria;
$c->addAscendingOrderByColumn(WordPeer::HEADWORD);

if (isset($_GET['limit']) && str_ievpi($_GET['limit'])) {

    $c->setLimit($_GET['limit']);

};

if (isset($_GET['q']) && (preg_match('/^[a-z]+$/ui', $_GET['q']))) {

    $c->add(WordPeer::HEADWORD, $_GET['q'] . '%', Criteria::LIKE);

}

$slowa = WordPeer::doSelect($c);

foreach ($slowa as $s) {
    echo $s->getHeadword() . "\r\n";
}

Listing 4. Baza danych — skrypt podaj-wyrazy.php

4.3 Skrypt podaj-wyjasnienie.php wykorzystujący bazę danych

W skrypcie odpowiedzialnym za pobieranie wyjaśnienia z bazy danych najpierw sprawdzamy, czy zostało podane słowo. Jeśli nie, to drukujemy słowo brak:

if (isset($_GET['word']) && (preg_match('/^[a-z]+$/ui', $_GET['word']))) {

    ...

    
} else {

    echo 'brak';
    
}

Jeśli słowo zostało podane, to tworzymy kryteria i pobieramy z bazy danych słowa:

$c = new Criteria;
$c->add(WordPeer::HEADWORD, $_GET['word']);
$slowa = WordPeer::doSelect($c);    

Jeśli pobrana lista nie jest pusta, przetwarzamy ją, drukując wyjaśnienia wszystkich słów:

if (!empty($slowa)) {
    foreach ($slowa as $slowo) {
        echo $slowo->getExplanation() ."\r\n\r\n";
    }    
}

Kompletny skrypt jest przedstawiony na listingu 5.

require_once 'propel/Propel.php';
require_once 'dictionary/Word.php';

Propel::init('dictionary-conf.php');

require_once 'walidacja.inc.php';

if (isset($_GET['word']) && (preg_match('/^[a-z]+$/ui', $_GET['word']))) {

    $c = new Criteria;
    
    $c->add(WordPeer::HEADWORD, $_GET['word']);
    
    $slowa = WordPeer::doSelect($c);    
    
    
    if (!empty($slowa)) {
        foreach ($slowa as $slowo) {
            echo $slowo->getExplanation() ."\r\n\r\n";
        }    
    }
    
    
} else {

    echo 'brak';
    
}

Listing 5. Baza danych — skrypt podaj-wyjasnienie.php

Słowa zawarte w słowniku (ang. headword, entry) nie są unikalne. Stwierdzisz to szukając w słowniku angielsko-polskim wyrazu plumb. Dlatego po wywołaniu

$c = new Criteria;
$c->add(WordPeer::HEADWORD, 'plumb');
$slowa = WordPeer::doSelect($c);    

tablica $slowa będzie zawierała kilka elementów.


Reklama

Szkolenia z Zend Framework 2.0