Witaj, Gościu O nas | Kontakt | Mapa
Wortal Forum PHPEdia.pl Planeta Kubek IRC Przetestuj się!

AJAX - porządkowanie aplikacji

Przykład w stylu Google Suggest z HTML_AJAX

Pora na nieco bardziej zaawansowany przykład: pole podpowiedzi podobne do mechanizmu Google Suggest (http://www.google.com/webhp?complete=1&hl=en), ale służące do wyszukiwania pakietów PEAR (patrz też Ramka Wzorzec AJAX Suggest).HTML_AJAX pozwala zarządzać interakcją klienta z serwerem w kilku prostych wierszach kodu. Jak widać na Listingu 4, klasa obsługująca stronę PHP jest dość prosta. Dla potrzeb przykładu korzystamy z tablicy zawierającej możliwe hasła wyszukiwania, choć w rzeczywistej aplikacji byłyby one prawdopodobnie pobierane z bazy danych. Lista wyszukiwania wymaga tylko jednej metody getString(), która porównuje przekazany ciąg znaków z kolejnymi pozycjami tablicy. Pasujące elementy są następnie kopiowane do tablicy wyników, która jest ostatecznie zwracana.Teraz uruchamiamy serwer usługi (Listing 5). W tym przykładzie skorzystamy z klasy AutoServer, która rozszerza podstawową klasę serwera i dodaje metodę inicjalizacyjną dla każdej klasy. Pozwala to zarządzać eksportem kilku klas PHP za pomocą jednego serwera - wystarczy ustawić wartość zmiennej $initMethods na true i nadać metodom inicjalizacyjnym nazwy w postaci initNazwaKlasy, co dla naszej klasy oznacza utworzenie metody initSuggest(). Wykorzystanie klasy AutoServer w tak prostym przykładzie to oczywiście strzelanie z armaty do muchy, ale pokazuje ciekawe możliwości biblioteki HTML_AJAX, które mogą się bardzo przydać w większych projektach.I to by było na tyle po stronie PHP. Jeśli nasza metoda działa poprawnie i nie generuje żadnych błędów, to nie musimy jej więcej zmieniać i możemy się zająć implementacją po stronie klienta. Rzut oka na Listing 6. pokazuje, że zaczynamy od dołączenia JavaScriptu dla serwera:

<script type='text/javascript'
  src='auto_server.php?client=
  all&stub=suggest'></script>

Następnie tworzymy kod obsługi żądania w postaci metody do_suggest() oraz funkcję zwrotną do wyświetlania wyników, a na koniec tworzymy nową instancję zdalnej wyszukiwarki AJAX. Reszta kodu to prostu formularz z jednym polem tekstowym i elementem <div> do wyświetlania wyników. Dodanie do pola tekstowego obsługi zdarzenia onkeyup="do_suggest(); return false;" powoduje wywołanie funkcji do_suggest() po każdym zwolnieniu klawisza (zdarzenie onkeypress byłoby obsługiwane zbyt wcześnie).

Jak to działa?

Każda zmiana wartości pola tekstowego powoduje wywołanie funkcji do_suggest(), która z kolei wywołuje metodę remoteSuggest.getstring() javascriptowej klasy HTML_AJAX. Ta komunikuje się z serwerem, który odsyła tablicę pasujących podpowiedzi przekazywaną następnie funkcji zwrotnej, która kończy cały proces dokonując niezbędnych zmian w strukturze dokumentu i wyświetlając podpowiedzi w ramach elementu <div>.

W ten sposób mamy już działający, choć nie najpiękniejszy przykład. Po pierwsze, funkcja autouzupełniania przeglądarki w tym przypadku tylko przeszkadza. Możemy ją jednak łatwo wyłączyć dodając do pola tekstowego atrybut autocomplete="off". Po drugie, sposób wyświetlania podpowiedzi pozostawia bardzo wiele do życzenia. Spróbujmy więc ulepszyć funkcję zwrotną - Listing 7. przedstawia poprawiony kod.

Po usunięciu poprzedniej zawartości elementu resultDiv, wyświetlającego wyniki, opakowujemy każdy wynik w osobny znacznik <span> dla uzyskania lepszej kontroli nad formatowaniem, po czym w pętli for dodajemy kolejne wyniki do warstwy resultDiv. Etap opakowania wykonujemy wywołując metody JavaScriptu document.createElement("span") i appendChild(). Dla zwiększenia czytelności przydałoby się jeszcze nieco stylu (Listing 8). Najważniejszy jest tu wpis powodujący wyświetlanie podpowiedzi jedna pod drugą zamiast w jednym wierszu:

#suggestions span {
  display: block;
}

Warstwa wyników powinna początkowo być ukryta, więc w pliku CSS podajemy dla niej atrybut display: none, który po otrzymaniu wyników przełączamy na wartość block w ramach metody zwrotnej:

resultDiv.style.display='block';
if (!resultSet)
  resultDiv.style.display='none';

Dodatkowe sprawdzenie zapobiega wyświetleniu warstwy, gdy serwer nie zwróci żadnych podpowiedzi.Pora dodać do wyników nieco interakcji - na razie tylko widzimy podpowiedzi, ale nie możemy wybierać pozycji z listy. Efekt wybierania osiągniemy dodając obsługę zdarzeń do elementu <span> każdego wyniku:

result.onmouseover = highlight;
result.onmouseout = unHighlight;
result.onmousedown = selectEntry;

Spowoduje to dodanie funkcji JavaScript do każdego zdefiniowanego zdarzenia. Działanie funkcji highlight() i unHighlight() polega po prostu na zmianie klasy CSS elementu <span>:

function highlight (){
  this.className='highlight';
}

Klasa CSS highlight wygląda tak:

.highlight {
  background-color: 0000ff;
  color: fff;
}

Minimalna wersja naszej wyszukiwarki powinna obsługiwać zastąpienie zawartości pola tekstowego podpowiedzią klikniętą przez użytkownika. Pole ma identyfikator string, więc podmiana jego treści jest prosta:

function selectEntry () {
  document.getElementById('string')
    .value = this.innerHTML;
}

Rysunek 3. Serwer podpowiedzi w akcji

Wzorzec AJAX Suggest

Listing 4. Klasa implementująca serwer podpowiedzi (plik suggest.class.php)

class suggest {
   function suggest() {
      require_once 'pear_array.php';
      $this->strings = $aPear;
   }
   function getString($input='') {
      if ($input == '') return '';
      $input = strtolower($input);
      $suggestStrings=array();
      foreach ($this->strings as $string) {
         if (strpos(strtolower($string),$input) === 0) {
            $suggestStrings[] = $string;
         }
      }
      return $suggestStrings;
   }
}

Listing 5. Serwer podpowiedzi w HTML_AJAX (plik auto_server.php)

session_start();
require_once 'HTML/AJAX/Server.php';
class AutoServer extends HTML_AJAX_Server {
   // Ustawienie tego znacznika jest konieczne, by korzystać z metod inicjalizacyjnych
   var $initMethods = true;
   // Metody inicjalizacyjne dla klasy podpowiedzi
   function initSuggest() {
      require_once 'suggest.class.php';
         $suggest = new suggest();
         $this->registerClass($suggest);
   }
}
$server = new AutoServer();
$server->handleRequest();

Listing 6. Prosty klient podpowiedzi

<html>
<head>
  <title>HTML_AJAX Suggest</title>
  <script type='text/javascript'
    src='auto_server.php?client=all&stub=suggest'></script>
  <script>
   function do_suggest() {
      remoteSuggest.getstring(document.getElementById('string').value);
   }
   // Stworzenie tablicy asocjacyjnej do składowania metod zwrotnych
   var suggestCallback = {
      getstring: function(result) {
         document.getElementById('suggestions').innerHTML = result;
      }
   }
   // Utworzenie obiektu zdalnego. Jego nazwa jest odwzorowana małymi literami, gdyż w nazwach klas i funkcji PHP4 wielkość liter nie jest rozpoznawana. Rejestrując każdą klasę na serwerze można przywrócić rozróżnianie wielkości liter.
   var remoteSuggest = new suggest(suggestCallback);
  </script>
</head>
<body>
  <div>
    Podaj nazwę pakietu PEAR:
    <input type="text" name="string" id="string" size="20" onkeyup="
      do_suggest(); return false;">
    <input type="button" name="check" value="Podpowiedz..." onclick="do_suggest();
      return false;">
  </div>
  <div id="suggestions">&nbsp;</div>
</body>
</html>

Listing 7. Ulepszona metoda zwrotna

var suggestCallback = {
   getstring: function(resultSet) {
      var resultDiv = document.getElementById('suggestions');
      resultDiv.innerHTML = '';
      for(var f=0; f<resultSet.length; ++f){
         var result=document.createElement("span");
         result.innerHTML = resultSet[f];
         resultDiv.appendChild(result);
      }
   }
}

Listing 8. Style CSS dla klienta podpowiedzi

* {
  padding: 0;
  margin: 0;
  font-family : Arial, sans-serif;
}
#suggestions {
  max-height: 200px;
  width : 306px;
  border: 1px solid #000;
  overflow : auto;
  margin-top : -1px;
  float : left;
}
#string {
  width : 300px;
  font-size : 13px;
  padding-left : 4px;
}
#suggestions span {
  display: block;
}

Listing 9. Ostateczna wersja klienta podpowiedzi

<html>
<head>
  <title>Podpowiedzi HTML_AJAX</title>
  <link rel="StyleSheet" type="text/css" href="suggest3.css" />
  <script type='text/javascript'
    src='auto_server.php?client=all&stub=suggest'></script>
  <script>
   var string = '';
   var oldstring = '';
   var timeout= 1000; /* czas w ms między sprawdzeniami - dobrą wartością jest 250 */
   function do_suggest() {
      string = document.getElementById('string').value;
      if (string != oldstring) {
         /* Przy pustym polu nie wysyłaj żądania...  */
         if (string) {
            remoteSuggest.getstring(string);
         }
         /* ... tylko ukryj warstwę */
         else {
            document.getElementById('suggestions').style.display = 'none';
         }
         oldstring = string;
      }
      window.setTimeout('do_suggest()', timeout);
   }
   // Stworzenie tablicy asocjacyjnej do składowania metod zwrotnych
   var suggestCallback = {
      getstring: function(resultSet) {
         var resultDiv = document.getElementById('suggestions');
         resultDiv.innerHTML = '';
         resultDiv.style.display = 'block';
         if (!resultSet) resultDiv.style.display = 'none';
         else{
            for(var f=0; f<resultSet.length; ++f){
               var result=document.createElement("span");
               result.innerHTML = resultSet[f];
               result.onmouseover = highlight;
               result.onmouseout = unHighlight;
               result.onmousedown = selectEntry;
               resultDiv.appendChild(result);
            }
         }
      }
   }
   // Utworzenie obiektu zdalnego
   var remoteSuggest = new suggest(suggestCallback);
   // Funkcje obsługi interakcji
   function highlight (){ this.className = 'highlight'; }
   function unHighlight () { this.className = ''; }
   function selectEntry () {
      document.getElementById('string').value = this.innerHTML;
   }
   </script>
</head>
<body onload="do_suggest()">
  <h1>HTML_AJAX Example: Suggest</h1>
  <p>Uwaga: czas między sprawdzeniami jest ustawiony na 1000ms dla celów demonstracyjnych. W praktyce lepiej korzystać z wartości rzędu 350ms.</p>
  <div id="error"></div>
  Podaj nazwę pakietu PEAR:
  <form method="get" id="suggest">
    <input type="text" name="string" id="string" size="20" autocomplete="off">
    <input type="button" name="check" value="Podpowiedz..." onkeyup="do_suggest();
      return false;">
    <div id="suggestions">&nbsp;</div>
  </form>
</body>
</html>
Informacje na podobny temat:
Wasze opinie
Wszystkie opinie użytkowników: (4)
przykłady
Niedziela 31 Maj 2009 6:27:19 pm - Tomplus

Szkoda że nie ma przykładowego zastosowania tych kodów... aby zobaczyć jak powinno działać.

AJAX...
Środa 28 Luty 2007 1:47:32 pm - pawelpaciorek <brak_at_maila.pl>

może jest tępy ale przeczytałem i nie bardzo wiem o co chodzi. Jeśli to ma być dla początkujących nie jasno napisane jak cholera, niektóre rzeczy biorą się z kosmosu i nie bardzo wiadomo co się z czym je :/
no chyba ze dla ludzi którzy są oblatania w temacie, to ja przepraszam...

przykład w stylu Suggests
Niedziela 03 Grudzień 2006 1:35:42 am - unseen <mj.keepitreal_at_gmail.com>

genralnie ok, poza literówką - w kodzie klienta jest getstring - a powinno być getString.

No i w sumie to mam problem z biblioteka HTML_Ajax, przy zabawie na plikach php jest ok, ale rpzy łączeniu się z bazą mysql poprzez PHP nie wygląda to już tak dobrze...

ubiegłego roku?
Poniedziałek 31 Lipiec 2006 2:52:15 pm - mroq <mroq_at_irc.pl>

"Na szczęście od ubiegłego roku istnieje rozwiązanie wielu z tych problemów."

Chyba trochę dłużej o ile mnie pamięć nie myli.

Mentax.pl    NQ.pl- serwery z dodatkiem świętego spokoju...   
O nas | Kontakt | Mapa serwisu
Copyright (c) 2003-2024 php.pl    Wszystkie prawa zastrzeżone    Powered by eZ publish Content Management System eZ publish Content Management System