ferrante.pl

  • blog
  • nauka, kurs javascript, kurs jquery
  • o mnie

Zmiany w jQuery 1.4

  • JavaScript
  • jQuery
data publikacji:

16/01

liczba komentarzy:
12

Zespół jQuery z Johnem Resigiem na czele wypuścił właśnie wersję 1.4 frameworka jQuery, który lubimy i cenimy (choć nie jest doskonały). W związku z tym powstała specjalna strona 14 dni jQuery, gdzie codziennie będzie pojawiać się jakaś niespodzianka związana z premierą nowego jQuery. Przyjrzyjmy się zmianom.

Lepsza dokumentacja API

Przede wszystkim warto zauważyć metamorfozę strony z dokumentacją. Starą docs.jquery.com (pozostanie online jeszcze przez jakiś tydzień) zastąpiła nowa api.jquery.com. Od tej pory wszystkie funkcje jQuery są wylistowane na stronie głównej – nie trzeba szukać i domyślać się, do której kategorii należy to, czego szukamy. Całość działa na Wordpressie i co zauważyli twórcy – odbiło się to na szybkości działania. Z większych ciekawostek warto nadmienić, że od teraz każda funkcjonalność posiada informację, kiedy została wprowadzona do jQuery – licząc od wersji 1.0. Oprócz tego dostępny jest też dump API w XML.

Co nowego?

Wersja 1.4 wygląda teraz tak, jeśli chodzi o rozmiar:

  • wersja zminifikowana i gzippowana – 23kb
  • wersja developerska – 154kb

Przyspieszyły funkcje empty(), remove(), html(), css(), attr(), addClass(), removeClass(), hasClass(), append(), prepend(), before() oraz after().

Mamy wreszcie settery w funkcjach takich jak ..css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass() oraz .toggleClass(). Czym są settery? Otóż to funkcje, które możemy przekazać jako argument. Muszą one zwracać wartość, która zostanie bezpośrednio zaaplikowana do jednej z powyższych metod.

$('.inner').wrap(function() {
	return '<div class="' + $(this).text() + '" />';
});

Powyższy kawałek kodu opakuje każdy element o klasie inner w div z klasą o nazwie zwróconej przez text, uruchomionej na każdym elemencie .inner.

Ponadto wybrano funkcje, które oferują naszym setterom także aktualne wartości, w zależności od kontekstu. Są nimi .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass() oraz .toggleClass(). Działa to tak, że ta wartość jest dostępna jako drugi argument przekazywanej przez nas funkcji:

$('a').html(function(i, html){
	return html.replace(/&/gi,'&');
});

W tym wypadku pod zmienną html będziemy mieli nic innego, jakby wynik funkcji $(this).html() wywołanej na każdym znalezionym tagu a.

Zmienił się trochę obiekt ajax. Lepsze serializowanie parametrów:

{foo: ["bar", "baz"]}

zamieni się w

foo[]=bar&foo[]=baz

W poprzedniej wersji byłoby to tak:

foo=bar&foo=baz

Jeśli jednak chcemy używać nadal starego sposóbu serializowania, można go uruchomić na trzy sposoby:

// włącza tradycyjny sposób serializowania dla wszystkich operacji ajaxowych
jQuery.ajaxSettings.traditional = true;

// włącza tradycyjny sposób serializowania dla pojedynczej operacji
jQuery.param( stuff, true );

// włącza tradycyjny sposób serializowania dla pojedynczego requestu ajaxowego
$.ajax({ data: stuff, traditional: true });

Poza tym, kiedy request ajaxowy zwraca application/json, parametr dataType jest równy JSON. Jeśli jest to text/javascript lub application/x-javascript dataType przyjmuje script i kod jest automatycznie wykonywany.

Co więcej, jQuery ignoruje w zapytaniach ajaxowych flagę Last-Modified i za każdym razem dostarcza aktualną, zwróconą wartość żądania, nie sugerując się cache przeglądarki. Można zmienić to zachowanie, ustawiając ifModified: true. jQuery wspiera także nagłówek If-None-Match.

JSON!

jQuery używa teraz natywnego parsowania danych JSON, jeśli tylko takie wspierane jest przez przeglądarkę. Nasze dane są też walidowane, więc coś takiego nie przejdzie:

{foo: "bar"}

HTML5

Co ciekawe, nowe typy formularzy z HTML5, jak np.:

<input type="datetime-local" />

będą uwzględniane przy serializowaniu danych formularzy.

Ajax context

Oprócz tego, przy zapytaniach ajaxowych można teraz ustalić kontekst, w jakim mamy odpalić metodę success:

$.ajax({
	url: "test.html",
	context: document.body,
	success: function(){
		$(this).addClass("done");
	}
});

W ten sposób, po wykonaniu się zapytania, tagowi body ustawiona zostanie klasa done.

$.ajax({
	url: "test.html",
	context: $("#foobar"),
	success: function(data){
		$(this).html(data);
	}
});

Analogicznie, po tej operacji, jeśli wszystko się powiedzie, elementowi #foobar zostanie automatycznie wstawiony, powiedzmy, kawałek HTMLa, który pobraliśmy sobie z pliku test.html, i który jest dostępny pod zmienną data.

Co ważne, funkcja success przyjmuje teraz 3 argumenty:

$.ajax({
	url: "test.html",
	context: $("#foobar"),
	success: function(data, status, xhr){
		$(this).html(data);
	}
});

Pod pierwszym mamy zwróconą przez request wartość, pod drugim status operacji, a pod trzecim obiekt ajax (to co jest pod $.ajax).

Warto też zwrócić uwagę, że tym razem jQuery nie ignoruje contentType w zapytaniach ajaxowych. Jest on teraz zawsze wysyłany. Pojawiła się tez możliwość ustawienia callback‘a dla JSONP – poprzez atrybut jsonpCallback , natomiast zapytania cross-domainowe są teraz o wiele bardziej wydajne.

Szybkość tworzenia nowych obiektów

Zapomnij natychmiast o czymś podobnym:

var obj = $("<div />");
obj.css("background", "#ddd").html("something").click(function() { alert("foobar!"); }).appendTo("body");

Można to teraz zrobić o wiele bardziej kompleksowo:

var obj = $("<div />", {
	css: {
		background: "#ddd"
	},
	html: "something",
	click: function() { alert("foobar!"); }
}).appendTo("body");

.eq(-N), .get(-N)

Od teraz w funkcjach eq i get możemy użyć ujemnych wartości:

$("div").eq(-2);
$("div").get(-2);

W ten sposób wybierzemy elementy drugie od końca.

first() i last()

Jeśli mowa o końcu, developerzy dodali funkcję last, która zwróci nam ostatni element oraz first, analogicznie zwracającą pierwszy.

toArray()

Z nowych rzeczy pojawiła się także metoda toArray, która zamienia wszystko… w tablicę:

var arr = $('a').toArray();
typeof arr; // object
arr // [<a id="foo">, <a id="bar">]
arr[1].html("ustawiamy wartość html dla drugiego z kolei pobranego linka");

jQuery().ready() – nie działa!

Kod $().ready() przestał być wspierany. Zamiast tego użyj:

$(document).ready()

lub

$(function(){})

Wszystko dlatego, że $() zwraca teraz pustą tablicę.

typeof $() // object
$().length // 0

$(“tag”)

Developerzy zarzekają się dumnie, że powyższa konstrukcja znacznie przyspieszyła. Przekonajcie się sami! Co więcej, warto dodać, że przyspieszył również selektor #id tag np.:

$("#foobar div");

toggleClass

toggleClass() może ustawić teraz kilka klas naraz:

$("div").toggleClass("current active");

Efekty

Z fajnych rzeczy dodano także obsługę techniki per-property easing:

$("#clickme").click(function() {
	$("div").animate({
	width: ["+=200px", "swing"],
	height: ["+=50px", "linear"],
	}, 2000, function() {
      		$(this).after("<div>Ukończono animację!</div>");
  	});
});

Co to znaczy? Ano to, że możemy użyć różnych stylów animacji (swing, linear) dla różnych właściwości CSS (powyżej, co jasne, są to: width, height) jednocześnie.

$.proxy()

Co robi nowa funkcja proxy()? Otóż zmienia ona scope dla danej funkcji, co oznacza w gruncie rzeczy to, że łatwo możemy ustawić, co chcemy pod zmienną this:

var obj = {
	name: "John",
	test: function() {
		alert(this.name);
	}
};

$("#foobar").click($.proxy(obj, "test"));

// To także działa:
// $("#foobar").click($.proxy( obj.test, obj ));

W ten sposób funkcja test odwołuje się do obiektu obj poprzez this, stąd tez dostępna własność this.name. Porównajcie sobie to z czymś takim:

$("#foobar").click(function() {
	alert(typeof this.name);
});

Wyświetlone zostanie undefined, ponieważ w tym wypadku skrypt będzie szukal name w obiekcie jQuery.

bind i zdarzenia

W wersji 1.4 funkcja bind przyjmuje wiele zdarzeń:

$("#foobar").bind({
	click:  function() {},
	mouseover: function() {}
});

Jeśli mowa o nich to wprowadzono także zdarzenia focusin i focusout. Czym różnią się one od focus i blur? Są to bowiem zdarzenia bąbelkowe i na tym polega cały myk. Zainteresowanym polecam przeczytać na temat różnic na temat bubble oraz capture events.

Usprawnień doznały także live eventy. Teraz każde tradycyjne zdarzenie może być użyte przez live(). Wcześnie niektóre eventy były nieobsługiwane.

detach()

Nowa metoda detach usuwa dany tag z drzewa DOM, ale jQuery nadal trzyma go w pamięci, dzięki czemu możemy szybko dodać go gdzie indziej, tym bardziej, że zachowane są zdarzenia, które zaaplikowaliśmy wcześniej:

var foo = $("#foo").click(function() {});
foo.detach();
foo.appendTo("body");

W powyższym przykładzie usuwamy #foo z drzewa DOM w 2 linijce, ale nadal możemy go dodać gdzieś indziej, np. do body.

unwrap()

Co robi unwrap? Usuwa opakowanie według danego taga:

Kod:

<body>
    <div>
        <p>he</p> <p>he</p> <p>he</p>
    </div>
</body>
$('div').unwrap();

zwróci nam:

<body>
   <p>he</p> <p>he</p> <p>he</p>
</body>

Inne

Z ważniejszych rzeczy pojawiła się metoda, a w zasadzie setter offset, który pozwala ustawić offest dla elementu. Wcześniej mogliśmy tylko takowy pobrać. Jest także delay(), dzięki której możemy opóźniać animacje:

$("div").fadeIn().delay(4000).fadeOut();

W ten sposób animacja fadeOut wykona się dopiero po 4 sekundach po zakończeniu fadeIn.

Wprowadzono też clearQueue(), która czyści zdefiniwaną kolejkę. Usuwa ona tylko funkcje, które nie zostały jeszcze wykonane.

Poza tym poprawiono zachowanie metody index:

$("div.current").index();

Coś takiego zwróci 1 w podobnej sytuacji:

<p></p>
<div class="current"></div>
<p></p>

Wprowadzono także metodę has(). Dzięki niej z łatwością sprawdzimy, czy dany element zawiera w sobie inny:

<div id="foobar">
	<p class="foo"></p>
</div>
$("#foobar").has("p.foo").length; // 1

Zachowuje się tak samo jak:

$("#foobar:has(p.foo)").length;

Wprowadzono też: nextUntil(), prevUntil(), parentsUntil(). Działają one podobnie do next i analogicznych, z tym wyjątkiem, że wyszukujemy elementy aż do znalezienia tego, który podaliśmy jako argument. Np.:

$("body").nextUntil("#foobar").css("display", "none");

ukryje wszystkie elementy aż do wystąpienia tego o id foobar.

Z innych zmian (oj, napracowali się chłopaki, napracowali…) mamy funkcje takie jak:

  • $.isEmptyObject() – sprawdza, czy przekazany argument jest pustym obiektem tzn. czy nie ma żadnych składowych
  • $.isPlainObject() – sprawdza czy obiekt zawiera jakieś podobiekty. Np.:
    var obj = {
    	podObiekt: {}
    };
    $.isPlainObject(obj);

    Zwróci false, ponieważ zdefiniowaliśmy inny obiekt (podObiekt) wewnątrz obiektu.

  • $.contains() – jeśli podamy jako parametry dwa obiekty DOM i drugi z nich mieści się w pierwszym, funkcja zwróci true
  • $.noop – zwraca pustą funkcję (analogicznie do składowej frameworku Prototype – Prototype.K)
  • $.unique() – szuka wśród podanej tablicy duplikatów i wyrzuca je z tablicy, zwracając nową, bez powtarzających się elementów

Z innych ciekawostek .clone(true) kopiuje także dane z funkcji data(). Nie tylko zdarzenia!

To prawdopodobnie nie wszystkie zmiany w najnowszej wersji jQuery, lecz z pewnością wszystkie najważniejsze. Jak zawsze chłopaki z teamu Resiga odwalili kawał dobrej roboty. Warto więc przyjrzeć się nowemu jQuery oraz projektowi 14 dni z jQuery. Dawno nie działo się aż tyle pozytywnych rzeczy w tym projekcie.

Komentarze

  1. 1

    Dzięki za fajne wylistowanie nowych ficzerów! :-)

    autor komentarza:
    Maciek
    data komentarza:
    16/01/2010 @ 02:10
  2. 2

    Oj napracowali się chłopaki od jQuery, Ty przy tym wpisie też :)

    Takie małe pytanko:
    $("div").fadeIn().delay(4000).fadeOut();

    “W ten sposób animacja fadeOut wykona się dopiero po 4 sekundach po zakończeniu fadeIn.”

    Może się mylę, ale fadeOut wykona się 4 sekundy po rozpoczęciu fadeIn. Aby wykonało się 4 sekundy po zakończeniu trzeba by to podać jako callback dla fadeIn, np:
    $("div").fadeIn(function(){
    $(this).delay(4000).fadeOut();
    });

    autor komentarza:
    Vokiel
    data komentarza:
    16/01/2010 @ 08:54
  3. 3

    http://api.jquery.com/delay/

    Hm, chyba jest tak, jak piszę ;-):

    When this statement is executed, the element slides up for 300 milliseconds and then pauses for 800 milliseconds before fading in for 400 milliseconds.

    autor komentarza:
    ferrante
    data komentarza:
    16/01/2010 @ 12:28
  4. 4

    Świetny artykuł. Od długiego czasu nie widziałem tak dobrego wpisu o changelogu. “Dodano X, dodano Y, dodano Z” każdy potrafi powiedzieć. ;)

    autor komentarza:
    Nowaker
    data komentarza:
    16/01/2010 @ 12:43
  5. 5

    @ferrante
    Rzeczywiście, to jednak w innej sytuacji chain nie działał tak jak się spodziewałem, tak że trzeba było używać callback. Mój błąd.

    Np w połączeniu z funkcją css(). W przykładzie poniżej, kolor zmieni się wraz z rozpoczęciem pierwszej akcji, a nie po zakończeniu fadeOut() i fadeIn(). Jednak tutaj delay() też nie pomoże.
    $('#wrap').fadeOut(2000).fadeIn(2000).css({'color': 'green'});

    Dopiero taka konstrukcja zadziała:
    $('#wrap').fadeOut(2000).fadeIn(2000,function(){
    $(this).css({'color': 'red'});
    });

    autor komentarza:
    Vokiel
    data komentarza:
    16/01/2010 @ 14:36
  6. 6

    @Vokiel: ale $(‘#wrap’).fadeOut(2000).fadeIn(2000).delay(4000).css({‘color’: ‘green’}); czemu ma nie zadziałać niby?

    autor komentarza:
    dreame4
    data komentarza:
    16/01/2010 @ 15:00
  7. 7

    > czemu ma nie zadziałać niby?

    IMO nie zadziała, tj. funkcja $.css wykona się zaraz po rozpoczęciu animacji. Wiąże się to ze sposobem działania $.delay.
    $.delay wewnętrznie korzysta z kombinacji $.queue(callback) i $.dequeue, co oznacza obsługę kolejki wywołań. Zaś kolejkowane są funkcje z modułu Effects/Fx, a nie funkcje typu $.css.
    Każde wywołanie funkcji animacyjnej dodaje tę funkcję do kolejki, dlatego zostaną one wywołane jedna po drugiej a nie jednocześnie.
    Wywołanie $.queue(callback) wpycha kolejną funkcję do kolejki. Funkcja ta powinna wewnętrznie (bezpośrednio lub pośrednio) wykonać $.dequeue, inaczej nie wykonają się pozostałe funkcje z kolejki. I ten fakt wykorzystuje funkcja $.delay, która wykonuje $.dequeue po określonym interwale czasu (setTimeout). Algorytm działania jest po prostu banalny.

    autor komentarza:
    Rafał Kukawski
    data komentarza:
    16/01/2010 @ 16:54
  8. 8

    Dobra robota, Ferr :)

    autor komentarza:
    Szafranek
    data komentarza:
    17/01/2010 @ 17:02
  9. 9

    Świetny wpis! Strasznie się napracowałeś, ale — jak zwykle — efekt jest bardzo dobry :) Szkoda, że tak rzadko się tu coś nowego pojawia.

    autor komentarza:
    Damian
    data komentarza:
    17/01/2010 @ 18:49
  10. 10

    Wow, good job :)

    Dobre uzupełnienie wiadomości z tego artykułu:

    http://net.tutsplus.com/tutorials/javascript-ajax/jquery-1-4-released-the-15-new-features-you-must-know/

    Jutro trzeba bedzie siąść i jeszcze raz na spokojnie przeanalizować twój wpis :)

    autor komentarza:
    le_banana
    data komentarza:
    19/01/2010 @ 01:44
  11. 11

    No no, jQuery się rozbudowuje i udoskonala ;) Dobrze, może kiedyś, w idealnym świecie gdy Windows będzie Open Source’owy i nikt nie będzie używał IE6, to będę miał czas na poznanie jQuery bliżej. No, ale pozostanę przy Mootools. Myślę też o Prototype, który z Zend’em ładnie współgra ;D Ferrante, utrzymuj swój blog na wysokim poziomie i zdobądź odrobinkę czasu na nowe wpisy.

    autor komentarza:
    Misiur
    data komentarza:
    25/01/2010 @ 17:33
  12. 12

    A co jest lepsze jquery czy dojo czy motols czy prototype? W czym lepiej robić animacje i bajerki do stron?

    autor komentarza:
    thjgfj
    data komentarza:
    31/01/2010 @ 22:19

Dodaj komentarz

idź do góry
  • blog
  • nauka, kurs javascript, kurs jquery
  • o mnie
O mnie

Damian Wielgosik - Programista i dziennikarz. Od siedmiu lat koder front-end i back-end. Lubi dobre technologie. mail skype

Kategorie
  • CSS
  • Drawter
  • ferrante.pl
  • JavaScript
  • jQuery
  • PHP
  • Publicystyka
  • Rozmowy rolowane
  • Software
  • Usability
  • Vademecum
  • W sieci...
Czytam
  • Costa
  • Ludwik
  • Rafał Kukawski
  • RAFi
  • Szafranek
  • Warszawa78

Powered by Wordpress.
Copyright by Damian Wielgosik 2007-2010
Design by Dez.