AjaxGetContent - dynamiczna strona AJAX

W ostatnim czasie zastosowanie technologii AJAX staje się coraz bardziej popularne. Wykorzystywana jest nie tylko przy obsłudze i walidacji dynamicznych formularzy, elementów forum i systemów komentowania. Spotykamy również całe witryny oparte o dynamiczne pobieranie treści, bez konieczności pełnego przeładowywania stron.

W przeważającej jednak częsci witryny te posiadają dwa duże mankamenty: ich treść nie jest poprawnie indeksowana przez wyszukiwarki internetowe, nie obsługują również poprawnie przycisków nawigacyjnych przeglądarek (wstecz / dalej) oraz bieżącego linkowania w pasku adresu.

Z pomocą przychodzi opracowana przez nas wtyczka jQuery - AjaxGetContent.

Pozwala na zamianę klasycznej, standardowej strony na dynamiczną, ultraszybką witrynę opartą na wywołaniach AJAX, przy zachowaniu pełnej widoczności treści dla wyszukiwarek oraz obsłudze przycisków nawigacyjnych przeglądarki, a także możliwości otwarcia każdego linku w nowym oknie lub skopiowania go do schowka. Adres w pasku przeglądarki jest przy tym na bieżąco aktualizowany. Dodatkowo każda załadowana podstrona jest poddana cache w pamięci podręcznej - jest pobierana tylko raz.

Najlepszym przykładem jest przeglądana obecnie przez Ciebie strona - kliknij na kilka odnośników, aby przekonać się jak działa nasza wtyczka (lub zobacz serwisy: Twój SkarbiecPanorama SmakuPTChPRiEFinestra).

Podstawowe założenia

Działanie wtyczki jest bardzo proste. Instalujemy ją dla standardowo wykonanej witryny. Wtyczka automatycznie przejmuje obsługę kliknięć na wszelkie linki, które podaliśmy przy jej wywołaniu. Po kliknięciu na dowolny z tych linków:

  • modyfikowany jest bieżący adres url w przeglądarce, poprzez dynamiczne zmodyfikowanie historii lub, gdy to niemożliwe (Internet Explorer), utworzenie zakładki z adresu docelowego (np. www.implico.pl/#podstrona.html); dzięki modyfikacji adresu zachowana jest funkcjonalność przycisków nawigacyjnych przeglądarki
  • wywoływana jest funkcja zwrotna (callback) onSend; funkcja może np. dokonywać animacji wygaszania bieżącej treści i/lub wyświetlać animowaną grafikę (pre/loader)
  • na adres linku wysyłane jest żądanie AJAX z dodatkowym, ustalonym parametrem, domyślnie "ajax_get_standard_content", w celu otrzymania treści dla danej podstrony
  • wywoływana jest funkcja zwrotna onReceive, która powinna obsłużyć (wstawić) otrzymaną treść dla danej podstrony oraz zakończyć ewentualne animacje wyświetlane podczas jej pobierania

Instalacja

Do poprawnego działania wtyczki wymagana jest biblioteka jQuery BBQ (Back Button & Query Library), dostępna pod adresem http://benalman.com/projects/jquery-bbq-plugin/.

Pierwszym krokiem jest włączenie pliku JavaScript:

<script type="text/javascript" src="js/jquery.ajaxGetContent.js"></script>

Plik zawiera również bibliotekę BBQ.

Następnie, dla szablonu treści należy uruchomić wtyczkę i określić parametry konfiguracyjne:

$('selektory_odnośników').ajaxGetContent( {
   zmienna_konfiguracyjna1 : wartosc1,
   zmienna_konfiguracyjna2 : wartosc2,
   //...itd.
});

Ważne jest, aby powyższy kod został uruchomiony dla każdej pobieranej podstrony (a więc również każdorazowo w treści wyniku żądania AJAX), tak żeby obsługa została ustawiona dla każdego istniejącego linku. Należy go więc umieścić jako kod inline (jeśli korzystasz z szablonów Smarty, praktyczne będzie umieszczenie kodu w bloku {strip}, aby zmniejszyć jego długość) lub w zewnętrznym pliku JavaScript wewnątrz funkcji, wywoływanej przy każdym przeładowaniu strony.

Konfiguracja

Dostępne są następujące parametry konfiguracyjne:

Parametr Wartość domyślna Opis
requestParameter "ajax_get_standard_content" Parametr, dołączany do żądania treści dla danej podstrony.
baseUrl "" (brak kontroli adresu) Dotyczy jedynie linkowania w trybie zakładek (IE). Określa podstawowy adres URL strony, np. "http://www.implico.pl/". Służy kontroli bieżącego adresu tak, aby zawsze miał postać "www.domena/#podstrona.html". W przypadku innej postaci adresu (np. www.domena/podstrona.html), strona jest przeładowywana.
useCache true Dla true, treść już odwiedzonych podstron jest zapisywana do pamięci podręcznej; przy ponownym kliknięciu na ten sam link dane nie są pobierane z serwera, a z pamięci podręcznej.
forceBookmarkLinking false Wymusza linkowanie oparte na zakładkach (standardowo wykorzystywane przy IE <= 9).
params {}

Parametry dodatkowe. Obiekt o następującej postaci:

{
'selektor' : { parametr1 : wartosc1... }
}

Dla elementów o podanym selektorze, do wywołania żądania treści dodawane są określone parametry GET. Więcej w sekcji przykładu zastosowania parametrów dodatkowych poniżej.

excludeAttr { 'rel' : 'lightbox', 'rel' : 'nofollow' } Obiekt zawierający atrybuty elementów, dla których brak jest wywołania AJAX. Standardowo są to linki lightbox i nofollow.
onHrefCheck
function(href, hrefParams)
{
return (href.length > 0) &&
((href.substr(href.length-1, 1) == '/') ||
(href.substr(href.length-5, 5) == '.html') ||
(href.substr(href.length-4, 4) == '.php'));
}
(domyślnie dopuszczone adresy: kończące się na "/" lub ".html" lub ".php")
Funkcja testująca poprawność adresu poszczególnych odnośników. Jako argumenty przekazywane są zmienne: href - adres odnośnika, hrefParams - ewentualne parametry GET (wraz z wiodącym znakiem "?"). Funkcja powinna zwrócić wartość true gdy adres jest poprawny lub false, gdy wywołanie AJAX powinno być zablokowane.
onElementCheck
function(element) {
return
!element.hasClass('no-ajax-load') &&
(element.attr('rel') != 'nofollow');
}
(domyślnie pomijane są odnośniki posiadające klasę "no-ajax-load" lub atrybut rel="nofollow")
 
Funkcja testująca kliknięty element odnośnika, jako argument otrzymuje obiekt jQuery. Zwraca wartość true gdy link powinien powodować wywołanie AJAX.
formsGet
{ 'form[method="get"]' :
function() { return true; } }
(obsługa wszystkich formularzy get)
Określa formularze typu get, których obsługa następuje automatycznie.
Obiekt o następującej postaci:
{
  selektor_formularza1 :
    funkcja_zwrotna() {...},
  selektor_formularza2 :
    funkcja_zwrotna() {...},
... }

Dla formularza o danym selektorze wywoływana jest funkcja_zwrotna (wcześniej uwzględniany jest ewentualny kod inline atrybutu onsubmit). W przypadku, gdy zwróci ona wartość pozytywną, na podstawie zawartości formularza (serializacja) tworzony jest nowy bieżący adres.
Aby wyłączyć obsługę formularzy get, zamiast obiektu należy podać wartość null.
formsPost null (brak obsługi formularzy post)

Określa formularze typu post, których obsługa następuje automatycznie.
Obiekt o następującej postaci:

{
  selektor_formularza1 : {
    onSend : funkcja() {...},
    onReceive : funkcja() {...} },
  selektor_formularza2 : {
    onSend : funkcja() {...},
    onReceive : funkcja() {...} },
... }

Dla formularza o danym selektorze wywoływana jest funkcja zwrotna onSend (wcześniej uwzględniany jest ewentualny kod inline atrybutu onsubmit). W przypadku, gdy zwróci ona wartość pozytywną, dane formularza są serializowane i wysyłane funkcją jQuery.ajax(). Jako funkcje zwrotne success i error ustawiona jest funkcja onReceive.

onSend
function(url) {}
Funkcja uruchamiana tuż przed wywołaniem treści poprzez AJAX. Służy np. do uruchomienia animacji lub innych efektów zaznaczających pobieranie podstrony.
onReceive
function(data, status) {}
Funkcja wywoływana po otrzymaniu treści poprzez AJAX. Argumenty: data - otrzymane dane, status - stan przekazany do funkcji zwrotnej przez funkcję $.ajax() ('success' w przypadku powodzenia).

Funkcje pomocnicze

Istnieją cztery funkcje dodatkowe:

  • $.fn.ajaxGetContent.clearCache()
    Usuwa cache zapisanych podstron (gdy parametr konfiguracyjny useCache = true).
  • $.fn.ajaxGetContent.load(url)
    Wymuszenie załadowania podanego adresu poprzez wywołanie AJAX. Gdy url = null, dokonywane jest ponowne przeładowanie bieżącej strony.
  • $.fn.ajaxGetContent.getCurrentUrl(full)
    Zwraca bieżący, wywoływany adres, np. "/podstrona.html". Funkcja pomocna przy zgłaszaniu aktualnej podstrony do Google Analytics (patrz przykład poniżej). Gdy parametr full = true, w przypadku pushState zwracany jest pełny adres (z nazwą protokołu i nazwą domeny).
  • $.fn.ajaxGetContent.scrollTo(id, always)
    Przesunięcie suwaka pionowego strony do poziomu elementu o podanym selektorze. Dokonywane jest tylko w kierunku do góry, gdy parametr always = true, przesunięcie dokonywane jest również w dół.

Przykład podstawowy

Poniżej prezentujemy przykładową konfigurację wtyczki. Jest to okrojona wersja konfiguracji dla naszej strony domowej, którą właśnie przeglądasz.

$(function()
{

    $('a').ajaxGetContent( {
       
        //podstawowy adres strony
        baseUrl : 'http://www.implico.pl/',
       
        onSend : function(url)
        {
            //ustawienie mniejszej przezroczystosci dla tresci na czas pobierania danych
            $('#ajax-load-area').css('opacity', 0.5);
        },

        onReceive : function(data, status)
        {
            data = $($.parseHTML(data, document, true));
            //dla jQuery < 1.9: data = $(data);

            if (status == 'success')
            {
                //wstawienie pobranej tresci
                $('#ajax-load-area').html(data);
               
                //przesuniecie suwaka do gory tresci
                $.fn.ajaxGetContent.scrollTo('#head');

                //inicjalizacja wszystkich skryptow, np. slidera
                initAllScripts();
               
                //Google Analytics - dopisanie aktywnej podstrony do statystyk
                if (window._gaq)
                    _gaq.push(['_trackPageview', $.fn.ajaxGetContent.getCurrentUrl()]);
            }

            //przywrocenie przezroczystosci dla tresci po pobraniu danych
            $('#ajax-load-area').css('opacity', 1);
        }

    });

});

Po stronie serwera

Jest to prawdopodobnie jedna z najbardziej problematycznych kwestii, z którą należy zmierzyć się podczas integracji wtyczki. Dla każdego wywołania strony z parametrem określonym w konfiguracji jako requestParameter (domyślnie "ajax_get_standard_content"), system powinien zwrócić jedynie treść, która ulega zmianie przy przełączeniu podstrony. W naszym przykładzie jest to zawartość elementu o identyfikatorze "ajax-load-area", a więc treść usytuowana z grubsza pomiędzy menu głównym a stopką strony.

Wtyczka jest w pełni kompatybilna z naszym autorskim systemem implicoCMS, nie dokonywaliśmy integracji z żadnym innym systemem. W przypadku implicoCMS, uruchomienie wtyczki dla gotowej, standardowej strony nie trwa więcej niż 10 minut. W razie wykrycia parametru "ajax_get_standard_content", ładowane i zwracane są jedynie szablony odpowiedzialne za treść indywidualną danej podstrony.

Oczywiście możliwe jest ignorowanie parametru requestParameter i zwracanie każdorazowo treści całej strony, a następnie wstawianie jedynie zawartości elementu "body". Jest to jednak mało efektywna metoda, choć z pewnością nawet ten zabieg przyspieszy działanie strony.

Zachęcamy do integracji i testowania działania wtyczki dla popularnych, istniejących systemów CMS. Opublikujemy wszelkie uwagi, instrukcje czy sugestie przesłane do nas.

Przykład: obsługa dynamicznego menu głównego

Zdarza się, że treść indywidualna danej podstrony nie ogranicza się do jednej, spójnej przestrzeni. Na przykład w menu głównym może następować podświetlenie aktywnej zakładki, podobnie jak na naszej stronie domowej. Rozwiązanie problemu jest bardzo proste. Należy do zwracanej treści dołączyć również zawartość aktualnego menu głównego, a następnie odnaleźć ten element, wstawić w odpowiednie miejsce, po czym usunąć. Przykład (nazwiązanie do przykładu głównego):

(...)
            if (status == 'success')
            {
                //pobranie elementu zawierajacego menu i wstawienie w odpowiednie miejsce na stronie
                $('.head-menu').html(data.find('.head-menu').html());
                //usuniecie elementu menu
                data.find('.head-menu').remove();
               
                //wstawienie tresci - bez menu
                $('#ajax-load-area').html(data);
(...)

Przykład: zastosowanie parametrów dodatkowych - obsługa linku "wstecz"

Przykładowym zastosowaniem parametru konfiguracyjnego params jest sytuacja, w której na stronie występuje przycisk "wstecz", a lokalizacji tej dotyczy stronicowanie. Sytuacja taka występuje w przypadku naszej podstrony Realizacje. Załóżmy, że znajdując się na drugiej stronie listy projektów, klikamy na dany projekt. Poniżej jego opisu znajduje się przycisk "wstecz", który powinien prowadzić do drugiej strony listy projektów. Aby poinformować skrypt zwracający treść i tworzący link "wstecz", że powrót powinien prowadzić do drugiej strony, dla kodu wywołującego wtyczkę dla drugiej strony listy projektów powinniśmy dodać następujący, przykładowy parametr (nawiązanie do przykładu głównego):

(...)
    $('a').ajaxGetContent( {
        'params' : {
            '.project-item a' : {
                'ajax_get_standard_content_back_page' : 2
            }
        },
(...)

Gdzie "project-item" jest klasą pojedynczego elementu projektu.

Po stronie serwera, skrypt powinien wykorzystać parametr "ajax_get_standard_content_back_page" do stworzenia odpowiedniego linku "wstecz", prowadzącego do drugiej strony listy projektów, tak jak to ma miejsce w przypadku naszej strony.

Demo

Przygotowaliśmy w pełni działającą, przykładową stronę:

Wymagania: serwer Apache z obsługą htaccess (lub emulator), interpreter PHP.

Przykłady zastosowań

Oto przykładowe strony, w przypadku których z powodzeniem zastosowaliśmy wtyczkę:

Adresy stron nadesłane przez czytelników:

 Zgodność

Wtyczka jest poprawnie obsługiwana przez wszystkie popularne przeglądarki (w tym IE od wersji 6), a także przeglądarki dla urządzeń mobilnych.

Rejestr zmian

Opublikowaliśmy następujące wersje:

  • Wersja 1.4 - automatyczna obsługa formularzy get/post
  • Wersja 1.3.3 - poprawiona obsługa zakładek (anchors)
  • Wersja 1.3.1 - krytyczna poprawka uwzględniająca błąd systemu Android w obsłudze zdarzenia popstate
  • Wersja 1.3: funkcja clearCache, usunięcie parametrów konfiguracyjnych excludeSelector i excludeUrl - w zamian dodanie parametru onElementCheck, automatyczne wywoływanie zdarzenia hashchange dla IE
  • Wersja 1.2: linkowanie oparte na popstate (zmiana URL w odróżnieniu od linkowania zakładkowego), poprawiona obsługa środkowego przycisku myszy
  • Wersja 1.1: cache odwiedzonych podstron
  • Wersja 1.0: linkowanie w oparciu o zakładki

 Licencja

Wtyczka jest publikowana na zasadach licencji MIT.

Do pobrania

Poniżej zamieszczamy linki do niezbędnych plików:

Zapraszamy również na nasze konto na GitHub i jQuery Plugin Registry.


W następnej części - "Klasa Params. Wygodna obsługa wielu parametrów metod w PHP". Zapraszamy do śledzenia artykułów.

 

All rights reserved © 2017 by implico.pl

Change language: en