//DEVGURU

Category archives ‘jQuery’

Rails, Ajax i jQuery

Tuesday, December 9th, 2008

Poniżej przedstawiam swoje podejście do wprowadzania ajaxowych funkcjonalności do aplikacji napisanych w Ruby on Rails. Jest to zbitka rozwiązań znalezionych na różnych blogach, forach oraz trochę moich przemyśleń. Do obsługi Javascript używam biblioteki jQuery, nie korzystam z jRails ani żadnych helperów do JS/Ajax dostępnych z Rails. Dzięki temu cały kod javascriptowy/htmlowy zaprezentowany poniżej może być bez trudu użyty w aplikacjach napisanych w innych językach/frameworkach. Zacznijmy.

Ruby on Rails a REST

Requesty ajaxowe różnią się trochę od zwykłych requestów, które dochodzą do serwera gdy użytkownik wpisze URL w przeglądarce. A przynajmniej powinny się różnić, żebyśmy po stronie serwera wiedzieli jaką odpowiedź (widok) zwrócić, nie ma bowiem sensu renderować całego layoutu np. dla requestu ajaxowego oceniającego zdjęcie w naszym serwisie. Tym aspektem odróżniającym różne typy requestów jest w tym przypadku nagłówek zawierający oczekiwany format odpowiedzi od serwera.

Dzięki implementacji REST w Railsach, sposób w jaki obsługujemy akcje jest zawsze taki sam niezależnie od typu requestu, jedyna zmiana dotyczy zwracanego przez nas widoku. Decydujemy o tym w kontrolerze:

To, który blok zostanie wywołany i w efekcie tego jaki widok zwrócony, zależy od route’ów zdefiniowanych w routes.rb oraz od oczekiwanego przez klienta formatu danych. W większości chcielibyśmy, żeby wszelkie ajaxowe requesty oczekiwały formatu XML (w odróżnieniu od HTML dla normalnych requestów), dlatego musimy zadbać o to, by przeglądarka odpowiednio ustawiała nagłówek Accept na ‘text/xml’ przy wywołaniach ajaxowych. W jQuery możemy ustawić to od razu dla wszystkich requestów z góry:

Różnice między przeglądarkami

Ręczne ustawienie nagłówka Accept niestety potrafi dawać różne efekty w różnych przeglądarkach. Wartością domyślnie ustawianą w przeglądarkach dla tego nagłówka jest text/html. Przy wywołaniu powyższego kodu Firefox zmieni wartość na ‘text/xml’, podczas gdy niektóre wersje IE i Safari ustawią ‘text/html; text/xml’ oczekując w ten sposób odpowiedzi od serwera w jednym z tych dwóch formatów.

Jest to dość istotna różnica, ponieważ Railsy decydując o tym, który format odpowiedzi wybrać, biorą pod uwagę pierwszy format napotkany w tablicy request.accept, którym w przypadku IE i Safari będzie text/html. Takie zachowanie zaobserwowałem chociażby w wersji 2.1.0 Railsów.

Poniższy kod naprawia opisane zachowanie przenosząc format xml na początek tablicy (jeśli się tam w ogóle znajduje), dzięki czemu będzie on znaleziony jako pierwszy.

Ajaxowe linki

Poniższy kod Javascript pozwala szybko zamienić istniejące już linki na działające ajaxowo. Proponuję go wrzucić do pliku appliacation.js.

 

Teraz wystarczy dodać do istniejących linków klasę (CSS’ową) get, post, put lub delete w zależności od pożądanej metody wywołania linku, by zmienić je w linki ajaxowe. Polecam do tego plugin LiveQuery, który to zachowanie automatycznie podepnie także do każdego nowego linku opatrzonego którąś z tych klas, który pojawi się na stronie (np. w efekcie działania jakiegoś wywołania ajaxowego). Dodatkowo do naszych linków możemy dodać opcjonalny atrybut ajaxtaget i ustawić jego wartość na selektor CSS’owy wskazujący na element, do którego zostanie załadowany widok zwrócony przez serwer.

Ajaxowe formularze

Do wysyłki formularzy porzez ajax będziemy potrzebować kolejnego pluginu – jQuery Form.

Ajaxowe formularze będą identyfikowane poprzez CSS’ową klasę ‘ajax’.

Modyfikacja strony po wywołaniu ajaxowym

Standardowym sposobem wyświetlania efektów wywołania ajaxowego jest odbieranie, obróbka i umieszczenie tego, co ono zwróci w jakimś miejscu na stronie. Innym sposobem jest umieszczenie całego kodu modyfikującego stronę w odpowiedzi zwracanej przez ajaxowe wywołanie i tylko wykonywanie go przez przeglądarkę. Taką funkcjonalność daje nam kolejny plugin do jQuery – Taconite. Cytując autora pluginu: “Taconite pozwala wykonywać modyfikacji wielu elementów strony naraz, korzystając z odpowiedzi zrwóconej przez pojedyncze wywołanie ajaxowe. Taconite używa do tego XML’owego dokumentu zawierającego instrukcję jak modyfikować stronę”.

Przykładowy widok XML z instrukcjami dla Taconite wygląda tak:

Dzięki podejściu oferowanym przez Taconite możemy poprawić strukturę aplikacji. Weźmy dla przykładu wspomnianą wcześniej funkcjonalność głosowania. Do tej pory kod Javascriptowy, który dbał o wyświetlenie rezultatów oddania głosu (np. zwiększenie countera, usunięcie linku ‘głosuj’, wyświetlenie komunikatu ‘głos został oddany’, itp) musiał być umieszczany na każdej stronie, na której było możliwe oddanie głosu. Teraz jest on po prostu zwracany jako odpowiedź serwera na oddanie głosu, czyli znajduje się tam gdzie być powinien.

Kolejny przykład – wyświetlanie flash messages w odpowiedzi na wywołania ajaxowe. Załóżmy, że to jest fragment layoutu naszej strony, w którym wyświetlamy komunikaty flash[:notice]:

Niech to będzie layout taconite, w którym zagnieżdzamy widoki zwracane na wywołania ajaxowe:

Teraz komunikaty flash[:notice] będą wyświetlane w standardowym miejscu na stronie z efektem fade-in. W podobny sposób możemy aktualizować inne elementy strony, np. wszelakie countery.

A Ty jakich narzędzi używasz?

Jestem ciekaw jakich rozwiązań używacie do implementacji Ajaxa w Waszych aplikacjach. Preferujecie jakieś inne pluginy/biblioteki?

Javascript, jQuery i preloading obrazków

Wednesday, November 26th, 2008

Wiemy już w czym problem, prawda? Chodzi o te pół, jedną trzecią, dwie szóste czy nawet całą, a nie daj Boże dwie i więcej sekundy, po których pojawia się obrazke zdefiniowany w css na zdarzeniu hover. Rozwiązań jest kilka, z czego na chwilę obecną przychodzi mi do głowy np. CSS Sprites, czyli działające-aczkolwiek-średnio-wygodne rozwiązanie.

Jakie rozwiązanie jest zadowalające-prawie-wszystkich a zarazem banalne w użyciu? Preloading przy użyciu jQuery.

Ot, cała filozofia: w DOMie tworzony jest obiekt img, który dostaje odpowiedni atrybut src, co powoduje wczytanie tego pliku do cache przeglądarki. Problem “opóźnionych hoverów” z głowy.

netguru friday talks… javascript

Saturday, November 24th, 2007

Co piątek, w okolicach godziny 14, przerywamy pracę nad projektami aby ugruntować swoją wiedzę związaną z programowaniem.

Dzisiejszy epizod “netguru friday talks” został poświęcony ugruntowaniu wiedzy na temat JavaScript. Rozmawialiśmy o nowoczesnym tworzeniu kodu, separacji JS i HTML, zasięgu, kontekście, operacjach na DOM, JS Closures, jQuery, pluginach do jQuery (jak tworzyć własne i z których istniejących warto korzystać).

Za tydzień o dobrych praktykach w serwisach /społecznościowych/ opowie Kuba. Znany Blogger, znany Designer i trzon netguru. Na pewno będzie ciekawie.

jQuery UI, jQuery 1.2 – najlepsze jest jeszcze lepsze!

Tuesday, September 11th, 2007

jQuery User Interface Library

To czego brakowało zwolennikom biblioteki jQuery to z pewnością brak akompaniującej biblioteki spełniającej zadania “prototype’owego” script.aculo.us’a. Biblioteka Interface – która pretendowała do tej roli – nie zyskała zbyt wielu sympatyków (powody: rozmiar, mała elastyczność, brak 100% kompatybilności z przeglądarkami). Twórca jQuery, John Resig, zapowiadał od kilku miesięcy, że jQuery dorobi się w końcu dopracowanej biblioteki obsługującej łebdwazerowe wodotryski. jQuery UI zapewni front-end developerom cały zestaw możliwości – drag&drop, zakładki (zapewne ze wsparciem dla przycisków nawigacji przeglądarki i zapamiętywaniem stanu via cookie), overlay i wiele innych… To wszystko już w niedzielę, 16. września. Nie mogę się doczekać!

Dla osłody dla wyczekujących jQuery Team wypuścił bibliotekę jQuery w odsłonie 1.2. Skok w numeracji wersji ma widoczne odzwierciedlenie w zmianach i nowych możliwościach. Wiele potrzebnych nowości, które powiększyły bibliotekę tylko o 5kB (biorąc pod uwagę wersję spakowaną p.a.c.k.e.r’em Deana Edwardsa, którą zapewne najczęściej się wykorzystuje w środowisku produkcyjnym).

Po pełną listę dodanych funkcjonalności odsyłam do WIKI jQuery. Moje faworyty to:

  • metoda offset(), która zapewnia dostęp do koordynatów elementu (top,left); oddzielna biblioteka dimensions będzie w wielu przypadkach zbędna
  • cross-domenowy JSON – od teraz nie trzeba tworzyć rozwiązań a’la proxy
  • poprawiona i rozbudowana serializacja wartości pól formularza – oddzielna biblioteka do obsługi formularzy będzie wielu w wypadkach zbędna
  • animacja stylu elementu w zakresie koloru, tła – wreszcie będziemy mogli tworzyć efektowne powiadomienia :-)
  • metoda triggerHandler() pozwalająca na wywołanie wszystkich event’ów przypisanych do konkretnego elementu DOM poza akcją domyślną
  • i ciekawa funkcja jak klonowanie fragmentu DOM wraz z przypisanymi do niego eventami.

Wielkie “jQuery’owe” święto