Development

Documentation/pl_PL/book/1.0/11-Ajax-Integration

You must first sign up to be able to contribute.

Version 15 (modified by Jarek.Kostrz, 10 years ago)
--

Rozdział 11 - Integracja AJAX'a

Interakcje po stronie klienta, kompleksowe efekty wizualne i asynchroniczna komunikacja są wspólne dla aplikacji Web 2.0. Wszystkie z nich wymagają JavaScript’u, ale kodowanie 'od ręki' jest często niewygodne i czasochłonne do debugowania. Szczęśliwie, symfony automatyzuje wiele ze wspólnych użyć JavaScript’u w szablonach z ukończonymi helperami. Wiele zachowań przeglądarek może być zakodowane bez ani jednej linii kodu JavaScript. Deweloperzy muszą troszczyć się tylko o efekt jaki chcą dokonać i symfony będzie radzić sobie z kompleksową składnią i kwestią kompatybilności.

Ten rozdział opisuje narzędzia dostarczone przez symfony ułatwiające tworzenie skryptów wykorzystywanych po stronie klienta:

  • Podstawowe helpery JavaScript tworzące zgodne ze standardami tagi <script> w szablonach symfony, do zaktualizowania elementu DOM (Document Object Model) lub trigger skrypt z linkiem
  • Prototype jest to biblioteka w JavaScript zintegrowana z symfony, która przyspiesza rozwój skryptów po stronie klienta przez dodawanie nowych funkcji i metod do jądra JavaScript
  • AJAXowe helpery pozwalają użytkownikowi na aktualizację części strony przez kliknięcie linka, wysyłać formularz lub modyfikować element formularza
  • Mnogość opcji w tych helperach dostarcza jeszcze większej elastyczności i mocy, szczególnie przez użycie funkcji callback.
  • Script.aculo.us jest inną biblioteką JavaScript, lecz również zintegrowaną z symfony, która dodaje dynamiczne wizualne efekty aby wzmocnić interface i doznania użytkownika
  • JavaScript Object Notation (JSON) jest standardem używanym do komunikacji pomiędzy serwerem i skryptem po stronie klienta
  • Kompleksowe interakcje po stronie klienta, połączenie wszystkich wyżej wymienionych elementów jest możliwe w aplikacjach symfony. Autouzupełnianie, drag-and-drop, sortowalne listy i edytowalny tekst, może być to wszystko zaimplementowane w pojedynczej linii w PHP – jako odwołanie do helpera symfony

Podstawowe Helpery w JavaScript

JavaScript przez bardzo długi czas był uważany jako mający małe realne użycie w profesjonalnych web aplikacjach przez brak kompatybilności z różnymi przeglądarkami. Dziś, kwestie kompatybilności są (w większości) rozwiązane i niektóre rozbudowane biblioteki pozwalają całościowo zaprogramować interakcje w JavaScript bez potrzeby pisania niezliczonych linii kodu i tracenia czasu na debugowaniu. Najbardziej popularnym awansem (advance) jest AJAX, który jest przedyskutowany w "AJAX Helpers" w późniejszym akapicie w tym rozdziale.

Paradoksalnie, zobaczysz bardzo mało kodu JavaScript w tym rozdziale. Dlatego że symfony ma oryginalne podejście do kodowania po stronie klienta: paczki i abstrakcyjne zachowania JavaScript’u są w helperach, więc Twoje szablony nie pokazują całego codu JavaScript. Dla deweloperów dodawanie zachowania do elementu na stronie, zajmuje jedną linię PHP, ale ten helper wywołuje kod w JavaScript i kontroluje wygenerowane odpowiedzi, które będę odkrywać całą ukrytą złożoność. Helpery tworzą z przeglądarką pewną jedność, kompleksowo ograniczają przypadki, rozszerzalność, tak więc większość kodu JavaScript jaki zawierają, może być istotny. Dlatego ten rozdział nauczy Cię jak nie używać JavaScript'u do osiągnięcia tego efektów, do których użyłbyś JavaScript'u.

Wszystkie z opisanych tutaj helperów są dostępne w szablonach, pod warunkiem, że zadeklarujesz użycie grupy helperów.

[php]
<?php use_helper('Javascript') ?>

Jak się wkrótce dowiesz, część z tych helperów zwraca kod HTML, a część kod JavaScript.

JavaScript w szablonach

W XHTML'u, bloki kodu JavaScript muszą być zamknięte w deklaracji CDATA. Ale strony wymagające wiele razy bloków kodu JavaScript, mogą stawać się nudne do pisania. To jest powodem dla którego symfony wprowadza helper javascript_tag(), który przetwarza kod w odpowiedni dla XHTML'a tag <script>. Listing 11-1 demonstruje użycie tego helpera.

Listing 11-1 – Wprowadzanie JavaScript'u z helperem javascript_tag()

[php]
<?php echo javascript_tag("
  function foobar()
  {
  ...
  }
") ?>
 => <script type="text/javascript">
    //<![CDATA[
      function foobar()
      {
        ...
      }
    //]]>
    </script>

Ale najbardziej powszechnym użyciem JavaScript, bardziej niż bloków kodu, jest w linku, który wywołuje pojedynczy skrypt. Helper link_to_function() właśnie to robi, ja pokazuje Listing 11-2.

Listing 11-2 – Wywoływanie JavaScript’u za pomocą linka z helperem link_to_function()

[php]
<?php echo link_to_function('Click me!', "alert('foobar')") ?>
 => <a href="#" onClick="alert('foobar'); return none;">Click me!</a>

Jak w helperze link_to(), możesz dodać opcje do tagu <a> jako trzeci argument.

NOTE Jeszcze helper link_to() ma swojego brata button_to(), możesz wywołać JavaScript z buttona () przez odwołanie się do helpera button_to_function(). Jeśli wolisz zdjęcie-link, zrób to tak: call link_to_function(image_tag('myimage'), "alert('foobar')").

Aktualizacja elementu DOM

Jednym ze wspólnych zadań w dynamicznych interfejsach jest aktualizacja elementu na tej stronie. To jest coś co zwykle piszesz, jak pokazane w listingu 11-3.

Listing 11-3 – Aktualizacje elementu w JavaScript

[php]
<div id="indicator">Data processing beginning</div>
<?php echo javascript_tag("
  document.getElementById("indicator").innerHTML =
    "<strong>Data processing complete</strong>";
") ?>

Symfony daje helper, który produkuje JavaScript, nie HTML, dla tego celu i jest nazwany update_element_function(). Listing 11-4 pokazuje użycie tego helpera.

Listing 11-4 – Aktualizacja elementu w JavaScript z helperem update_element_function()

[php]
<div id="indicator">Data processing beginning</div>
<?php echo javascript_tag(
  update_element_function('indicator', array(
    'content'  => "<strong>Data processing complete</strong>",
  ))
) ?>

Możesz być pełen zdumienia, dlaczego ten helper jest szczególnie przydatny, to jest co najmniej tak długie jak aktualny kod JavaScript. To jest rzeczywiście sprawa czytelności. Na przykład, możesz chcieć wstawić zawartość przed lub po elemencie, usunąć element zamiast zaktualizować go lub …(even do nothing according to a certain condition). W takich przypadkach, kod JavaScript staje się trochę zaśmiecony, ale update_element_function() utrzymuje szablon bardzo czytelnym, co możesz zobaczyć w listingu 11-5.

Listing 11-5 – Opcje helpera update_element_function()

[php]
// Wstawia zawartości tuż po elemencie 'indicator'
update_element_function('indicator', array(
  'position' => 'after',
  'content'  => "<strong>Data processing complete</strong>",
));

// Usuwa element przed 'indicator', i tylko gdy $condition jest prawdziwy
update_element_function('indicator', array(
  'action'   => $condition ? 'remove' : 'empty',
  'position' => 'before',
))

Helpery tworzą twoje szablony prostszymi do zrozumienia niż jakikolwiek kod JavaScript i masz pojedynczą składnie dla podobnych zachowań. To jest także, dlaczego nazwa helpera jest za długa: To czyni kod samowystarczalny, bez potrzeby dodatkowych komentarzy.

Wdzięczna Degradacja Tag <noscript> pozwala wyszczególnić kod HTML, który jest wyświetlany tylko gdy przeglądarka nie obsługuje JavaScript’u. Symfony dopełnia to helperem, co działa w inny sposób: Kwalifikuje część kodu, który przeglądarka obsługuje i następnie wykonuje go. Helpery if_javascript() i end_if_javascript() udogodniają tworzenie aplikacji, jak zademonstrowano w Listingu 11-6.

Listing 11-6 - Wykorzystanie helpera if_javascript() do zezwolenia na Wdzięczną Degradacje

[php]
<?php if_javascript(); ?>
  <p>You have JavaScript enabled.</p>
<?php end_if_javascript(); ?>

<noscript>
  <p>You don't have JavaScript enabled.</p>
</noscript>

NOTE Nie trzeba używać funkcji echo kiedy używasz helperów if_javascript() i end_if_javascript().

Prototype

Prototype jest wspaniałą biblioteką w JavaScript, która rozszerza możliwości programowania po stronie klienta, dodaje brakujące funkcje o których mogłeś marzyć i oferuje nowe mechanizmy do manipulacji DOM. Strona projektu: http://prototypejs.org/. Pliki Prototype zintegrowane z frameworkiem symfony i dostępne w każdym nowym projekcie, w web/sf/prototype/. To znaczy, możesz użyć Prototype przez dodanie następującego kodu do twojej akcji: $prototypeDir = sfConfig::get('sf_prototype_web_dir'); $this->getResponse()->addJavascript($prototypeDir.'/js/prototype');

lub przez dodanie w pliku view.yml: all: javascripts: [%SF_PROTOTYPE_WEB_DIR%/js/prototype]

NOTE Helpery AJAX’owe, opisane w następnej sekcji, opierają się na Prototype. Biblioteka Prototype już jest automatycznie włączana, jak tylko użyjesz jej. To znaczy, że nie będziesz potrzebował manualnie dodawać Prototype do odpowiedzi, jeśli szablony odwołają się do helpera a _remote.

Biblioteka Prototype jest ładowana jeden raz, możesz wykorzystać wszystkie z nowych funkcji dodanych do jądra. Ta książka nie ma na celu opisywać ich w całości, ale będziesz mógł łatwiej znaleźć dobrą dokumentację do Prototype:

  • Particletree: [http://particletree.com/features/quick-guide-to-prototype/]
  • Sergio Pereira: [http://www.sergiopereira.com/articles/prototype.js.html]
  • Script.aculo.us: [http://wiki.script.aculo.us/scriptaculous/show/Prototype]

Jedna z funkcji Prototype dodaje do JavaScriptu funkcję dolara, $(). Zasadniczo ta funkcja jest prostym skrótem do document.getElementById(), ale trochę potężniejsza. Zobacz listing 11-7 z przykładem użycia:

Listing 11-7 - Użycie funcji $() aby otrzymać elemet o określonym ID

[php] node = $('elementID');

// To znaczy to samo co node = document.getElementById('elementID');

// Ta funkcja może zwrócić więcej niż jeden element w tym samym czasie // i w tym przypadku rezultatem będzie tablica z elementami DOM. nodes = $('firstDiv', 'secondDiv');

Prototype daje także funkcję, uzupełniającą braki JavaScript’u, która zwraca tablicę, elementów DOM które mają klasę podaną jako argument: [php] nodes = document.getElementByClassName('myclass');

Jednakże, rzadko będziesz tego używał, ponieważ Prototype daje jeszcze wspanialszą funkcję, nazwaną podwójnym dolarem, $$(). Ta funkcja zwraca tablicę elementów DOM opierając się na selektorze CSS. Więc poprzedni przykład może być następująco napisany: [php] nodes = $$('.myclass');

Dzięku mocy selektorów CSS, możesz parsować drzewo DOM ze względu na class’ę, ID, dziecko-rodzica (parent-child) i poprzedni-następny pokrewny element, nawet łatwiej niż mógłbyś to zrobić za pomocą wyrażeń XPath. Masz także możliwość pisania skomplikowanych selektorów, jak ten: [php] nodes = $$('body div#main ul li.last img > span.legend');

Jednym, ostatnim przykładem uwydatniania składni dostarczanej przez Prototype jest each iterator tablicy. To ma tą samą zwięzłość jak w PHP, dodaje możliwość definiowania anonimowych funkcji i zamknięć w JavaScript. Prawdopodobnie używałeś tego dużo programując samodzielnie w JavaScript’cie. [php] var vegetables = ['Carrots', 'Lettuce', 'Garlic']; vegetables.each(function(food) { alert('I love ' + food); });

Ponieważ programowanie w JavaScirpit z Prototype jest bużo bardziej przyjemniejsze niż robienie tego samemu, od podstaw i ponieważ to jest także część symfony, powinieneś naprawdę spędzić kilka minut na przeczytanie dokumentacji związanej z tym.

Helpery AJAX'a

Co jeśli chciałeś zaktualizować element na stronie, nie z JavaScript jak w Listingu 11-5, ale ze skryptem w PHP wykonywanym po stronie serwera? To powinno dać ci okazję na zmianę części strony zgodnie z odpowiedzią serwera. Helper remote_function właśnie to robi, jak zademonstrowano w Listingu 11-8.

Listing 11-8 – Użycie helpera remote_function()

[php]

<?php echo javascript_tag( remote_function(array( 'update' => 'myzone', 'url' => 'mymodule/myaction', )) ) ?>

NOTE Parametr URL powinien zawierać każdy wewnętrzny URI (module/action?key1=value1&...) lub nazwę reguły routingu, tak jak w url_for().

Kiedy wywołamy, ten skrypt zaktualizuje element o id myzone, danymi z odpowiedzi lub prośby akcji mymodule/myaction. Ten rodzaj interakcji jest nazwany AJAX i to jest sercem wysoce interaktywnych web aplikacji. Tu jest jak Wikipedia ([http://en.wikipedia.org/wiki/AJAX]) opisuje to:

AJAX czyni strony internetowe bardziej wrażliwymi przez wymianę w tle, małych ilości danych, z serwerem, więc kompletna strona nie potrzebuje być przeładowywana za każdym razem, gdy użytkownik coś zmieni. To przyczyną wzrastającej interakcyjności, szybkości i użyteczności stron. AJAX działa na XMLHttpRequest, obiekt JavaScript zachowuje się jak ukryta ramka, którą możesz aktualizować odpowiedzią serwera i użyć ponownie do manipulowania resztą twojej strony. Ten obiekt jest bardzo niskiego poziomu i różne przeglądarki działają z tym w różny sposób, więc manualna obsługa próśb AJAX’a, zwykle znaczy pisanie długiego kodu. Na szczęście, Prototype zawiera cały niezbędny kod do wymiany danych przez AJAX i daje prostszy obiekt AJAX’a i symfony wykorzystuje go. Dlatego biblioteka Prototype jest automatycznie ładowana, kiedy tylko użyjesz helpera AJAX w swoim szablonie.

CAUTION Helpery AJAX nie będą działać jeśli URL zdalnej akcji nie będzie należał do tej samej domeny co bieżąca strona. To ograniczenie jest z powodu bezpieczeństwa i funkcjonujące w przeglądarkach ograniczenia nie mogą być ominięte.