Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu javascript Kanał ATOM (tag: javascript)

Autor wpisu: batman, dodany: 27.02.2011 22:04, tagi: javascript

W Internecie pojawiła się książka, obok której nie może przejść obojętnie nikt, kto interesuje się językiem JavaScript. Mowa o “Essential JavaScript Design Patterns For Beginners”. Wbrew temu co mówi tytuł książki, nie jest to pozycja tylko dla początkujących. Wyjadacze, którzy potrafią wyczarować JavaScriptem niemal wszystko, również znajdą w tej książce wiele ciekawych informacji.

Szczegółowe informacje na temat książki oraz linki pobrania znajdziecie na blogu autora – http://addyosmani.com/blog/essentialjsdesignpatternsupdate1/

Miłej lektury!

Autor wpisu: batman, dodany: 19.02.2011 08:00, tagi: css, javascript, php, jquery

Czym jest cheet sheat raczej tłumaczyć nie trzeba. Niejednokrotnie zerkałem na tablicę korkową/ścianę karton-gips naszpikowaną licznymi zadrukowanymi kartkami w celu znalezienia tej jednej jedynej, zawierającej odpowiedź na moje pytanie. Ściągawki są szybsze nawet od Google – zawsze pod ręką, nie wymagają do działa dostępu do Internetu (bez prądu też doskonale sobie radzą), zazwyczaj wystarczy rzut oka, by znaleźć rozwiązanie problemu.

Kilka dni temu Wookieb podesłał do mnie linka prowadzącego do strony zatytułowanej 100 + Must Have Cheat Sheets and Quick References For Web Designers and Developers. Nazwa mówi sama za siebie. Setka (a nawet więcej) obowiązkowych ściągawek, bez których żywot developera to droga przez mękę.

Nie przejrzałem wszystkich ściągawek, jednak po sprawdzeniu kilku najbardziej mnie interesujących, śmiało mogę napisać, iż tytuł nie został napisany na wyrost.

Co ciekawego znajdziemy na ściągawkach? Oto lista najciekawszych zagadnień:

  • CSS3
  • HTML5
  • WordPress
  • PHP
  • jQuery
  • czcionki
  • Adobe AIR

Miłej lektury.

Autor wpisu: sokzzuka, dodany: 18.02.2011 13:43, tagi: javascript, php

Jedną z największych zalet jak i wad Javascriptu jest jego ogromna elastyczność i prostota. Dlaczego zalet jak i wad ? Dzięki elastyczności możemy więcej. Jednak z drugiej strony, możliwość rozwiązania jakiegoś problemu na kilka sposobów zmniejsza rozumienie kodu. Prostota i unifikacja JS wokół konceptu funkcji z jednej strony umożliwia wykorzystanie jednego mechanizmu enkapsulacji w wielu kontekstach. Natomiast z drugiej jest przez wielu nierozumiana, zwłaszcza przez osoby przyzwyczajone do języków gdzie występuje wiele słów kluczowych, przy pomocy których owy mechanizm jest realizowany. Elastyczność JS pozwala nam na takie zabawy, jak implementację własnego modelu obiektowego w efektywny sposób. Jakie cechy JS wspomagają ten proces ?

  1. Obiekty anonimowe
  2. Funkcja ‘__noSuchMethod__’ (odpowiednik __call w php)
  3. Funkcje anonimowe i domknięcia leksykalne

Tak na prawdę, przy pomocy JS można zaimplementować dowolną odmianę modelu obiektowego, który znajduję się w innych językach. Zarówno modele oparte na klasach, metaklasach, ich wariacje jak i na prototypach – które są wbudowane w JS. W tym artykule, który ma charakter badawczo – eksperymentalny chciałbym po pierwsze przedstawić model obiektowy jaki wymyśliłem, a po drugie jego implementację przy użyciu ww. listy cech języka. Mam nadzieje, że artykuł was zainteresuje oraz zainspiruje do podobnych eksperymentów :) .

Skoro wiemy już jakiś środków użyjemy, należałoby postawić pytanie – co chcemy osiągnąć ?

Model obiektowy, który chciałbym zaimplementować będzie starał naśladować rzeczywistość. Założenia:

  1. Obiekty tworzone są w fabrykach
  2. Fabryki tworzą obiekty poprzez komponowanie ich z różnych elementów wg. planów / foremek
  3. Foremki są z natury niezmienne, ale można komponować z ich elementów nowe wzory wg uznania (można w ten sposób zaimplementować coś o funkcjonalności wielodziedzieczenia)
  4. Każdy obiekt po opuszczeniu fabryki żyje własnym życiem i przez swój cykl istnienia może diametralnie się zmienić w stosunku do swojego wzorca

Myślę, że założenia są dość logiczne i odzwierciedlają cykl jaki przechodzą właściwie wszystkie realnie istniejące obiekty na naszej planecie. Żeby nie być gołosłownym podam najbardziej oczywisty przykład – Samochód.

  1. Samochód jest tworzony w fabryce
  2. Fabryka tworzy samochód poprzez komponowanie go z różnych elementów (silnik, koła, skrzynia etc) wg projektu.
  3. Projekt samochodu jest raczej niezmienny, a jeżeli coś jest zmieniane to nazywa się to nowym modelem
  4. Samochód po opuszczeniu fabryki może trafić w ręce różnych ciekawych ludzi którzy np. poddadzą go wiejskiemu tuningowi, wtedy na 100% nie będzie  wyglądał tak jak go projektant narysował :)

Czas na kod! Na początek – plan/foremka/template:


var fooTemplate = {
    state: {
        foo: {
            value: 1
        }
    },
    behavior: {
        incrementFoo: {
            scope: 'public',
            value: function(self){
                self.state.foo++
                console.log (self.state.foo, 'incrementFoo');
            }
        },
        decrementFoo: {
            scope: 'internal',
            value: function(self){
                self.state.foo--;
                console.log (self.state.foo);
            }
        }
    }
}

Template został zadeklarowany jako anonimowy obiekt przypisany do zmiennej „fooTemplate”. Wewnątrz niego trzymamy metadane dotyczące tego jak skonstruować działające „coś”. Zmienne oznaczone są jako „state”, natomiast metody jako „behavior”. Każdy element z oprócz domyślnej wartości (value) posiada różne adnotacje. Zakładam, że wszystkie zmienne obiektu są prywatne. Natomiast metody, mogą być publiczne, albo prywatne (odpowiednio public i internal). Oczywiście można dodać różne inne adnotacje wzorem tych z Javy albo C#. Każda metoda jako pierwszy argument przyjmuje „self” – wewnętrzną referencję do obiektu, odpowiednik „this”.

Kolejnym rzeczą jaka będzie nam potrzebna to fabryka obiektów, która będzie wiedziała jak z template’u stworzyć obiekt. Dla takiego rodzaju template’u, jak wyżej zaprezentowany stworzyłem fabrykę w postaci funkcji „genericFactory”:


function genericFactory(template){
    var self = {
        state: {},
        behavior: {
            'public': {},
            'internal': {}
        }
    };

    for(var i in template.state){
        self.state[i] = template.state[i].value
    }

    for(var i in template.behavior){
        if(template.behavior[i].scope == 'public'){
            self.behavior['public'][i] = template.behavior[i]['value']
        } else {
            self.behavior['internal'][i] = template.behavior[i]['value']
        }
    }

    function obj(){

        this.__noSuchMethod__ = function __noSuchMethod__(id, args){
            if(self.behavior['public'][id] != undefined){
                args.unshift(self);
                return self.behavior['public'][id].apply(this, args);
            }
            throw 'No such method!'
        }
    }
    return new obj;
}

Przetwarza ona template na konkretną instancję obiektu oraz enkapsuluje go w obiekcie „obj”. Obiekt „obj” posiada jedną metodę „__noSuchMethod__”. Jest ona odpowiednikiem „__call” w PHP. Sprawdza ona, czy metoda, która chcemy wywołać z obiektu jest możliwa do wywołania (jej scope jest „public”). Jeżeli tak, to jest wywoływana i zwracany jest efekt jej działania.

Jak już pisałem, efektem takiego podejścia do tworzenia obiektów jest możliwość zasymulowania wielodziedziczenia. Potrzebne będą nam do tego – jeszcze jeden template, oraz funkcja miksująca:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: JoShiMa, dodany: 15.02.2011 23:24, tagi: jquery, javascript

Pracuję ostatnio nad dość ciekawym projektem, który realizuję wykorzystując kohana 2. Mimo mojej szczerej niechęci (ciągle) do JavaScript oraz zupełnej nieznajomości (nie powinnam się przyznawać?) mechanizmów AJAX musiałam się zmierzyć z pewnymi zagadnieniami, których puki co inaczej zrealizować się nie da. Opis problemu W serwisie, który tworzę będzie znajdowała się lista obrazków do których użytkownicy [...]

Autor wpisu: batman, dodany: 14.02.2011 08:00, tagi: javascript, jquery

Wraz z nadejściem jQuery 1.5, programiści otrzymali do swoich rąk szereg funkcjonalności usprawniających pracę z AJAXem. Jedną z nich są obiekty wstrzymane (deferred objects). W dużym skrócie dzięki deferred object możemy przypisać callback do AJAXowego requestu w dowolnym momencie, a nie jak to miało miejsce do tej pory, w momencie tworzenie requestu. Co więcej nie musimy ograniczać się tylko do jednej funkcji zwrotnej.

Jak to się robiło kiedyś…

Przed nastaniem jQuery 1.5 typowy request AJAXowy wyglądał następująco.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.5.js"></script>
        <script>
        $(document).ready(function() {
        	$.ajax({
        		url: "ajax.php",
        		type: "POST",
        		success: function(data) {
        			$("#content").append(data);
        		}
        	});
        });
        </script>
    </head>
    <body>
        <div id="content"></div>
    </body>
</html>

W efekcie działania tego nieco uproszczonego przykładu, do diva o identyfikatorze content dodana zostanie zawartość odpowiedzi serwera. Jeśli chcielibyśmy wykonać więcej operacji na zwróconych przez serwer danych oraz uzależnić niektóre operacje od wyniku działania innych funkcji, nieźle byśmy się napocili.

A jak to się robi dziś?

Na szczęście z pomocą przychodzi nam najnowsza odsłona jQuery. W wersji 1.5 opisany powyżej problem rozwiążemy w bardzo prosty sposób

$(document).ready(function() {
	var req = $.ajax({
		url: "ajax.php",
		type: "POST",
		success: function(data) {
			$("#content").append(data);
		}
	});

	/* dużo innych operacji, które muszą się wykonać niezależnie od AJAXa */

	req.success(function(data) {
		/* korzystamy z danych przetworzonych powyżej */

		// zrób coś z danymi z serwera
		$("#content").append(data);
	});
});

Drugi callback success wykona się dopiero w momencie, gdy zakończą się operacje znajdujące się bezpośrednio przed nim. Zmienna data zawierać będzie dokładnie te same dane, co w przypadku pierwszej funkcji callback. W podobny sposób możemy dodać callbacki error oraz complete.

Magia?

Obiekty wstrzymane (deferred object) wykorzystują wzorzec Promises/A. Zakłada on istnienie bytu nazwanego obietnicą (promise), który określa potencjalną wartość zwróconą w wyniku działania jakiejś operacji. Obietnica może znajdować się w jedenym z trzech stanów – niespełniona, spełniona, zakończona niepowodzeniem, przy czym zmiana stanu może nastąpić tylko raz: z niespełnionej na spełnioną lub z niespełnionej na zakończoną niepowodzeniem. W momencie gdy obietnica znajdzie się w stanie spełniona lub zakończona błędem, zmiana stanu nie może już mieć miejsca. Dzięki takiemu zachowaniu obietnic, dane zwrócone do callbacka pozostają niezmienne niezależne od miejsca, w którym do tych danych się odwołujemy.

W celu umożliwienia korzystania z wspomnianej przed chwilą funkcjonalności, jQuery zostało wyposażone w obiekt Deferred. To co się dzieje “behind the scenes”, wygląda łudząco podobnie do typowego wywołania metody ajax.

function funkcja1()
{
	var dfd = $.Deferred();
	dfd.resolve("ok");
	return dfd.promise();
}

function funkcja2()
{
	var dfd = $.Deferred();
	dfd.reject("my bad");
	return dfd.promise();
}

$.when(funkcja1(), funkcja2())
	.fail(function() {
		console.debug("co najmniej jedna funkcja sie wywaliła");
	})
	.done(function() {
		console.debug("wszystkie funkcje są ok");
	})
	.then(function() {
		console.debug("ok");
	}, function() {
		console.debug("coś poszło nie tak");
	});

Powyższy przykład nie jest może zbyt funkcjonalny, ale idealnie pokazuje zasadę działania obiektu Deferred. Metoda when przyjmuje jako argumenty dowolną ilość funkcji, których stan chcemy monitorować. Do obiektu zwróconego przez metodę when dodajemy handlery uruchamiane w momencie gdy wszystkie funkcje zakończą swoje działanie sukcesem (handler dome) lub co najmniej jedna z nich zakończy się niepowodzeniem (fail). Handler then przyjmuje dwa parametry. Pierwszym jest funkcja wykonywana w przypadku sukcesu, drugim funkcja wykonywana w momencie niepowodzenia.

Skąd metoda $.when wie czy monitorowane funkcje zakończyły się sukcesem lub porażką? Informuje ją o tym obiekt Deferred, który zwraca opisaną wcześniej obietnicę. Nim obietnica zostanie zwrócona, należy ustawić jej stan przy pomocy jeden z dwóch metod – resolve dla poprawnego sukcesu oraz reject dla porażki.

Słowo końcowe

Przedstawione powyżej informacje na temat deferred objects to tylko wierzchołek góry lodowej, której cały obraz ujrzycie po lekturze dokumentacji. Warto również zapoznać się z tym wpisem. Znajdziecie w nim szereg interesujących przykładów.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: batman, dodany: 07.02.2011 08:00, tagi: javascript

Podczas tworzenia niewielkich formularzy logowania, bardzo często można natknąć się na projekt graficzny zakładający domyślne wartości w polach login oraz hasło (zamiast etykiet obok pól) informujące użytkownika o rodzaju danych jakie ma wprowadzić. O ile login nie stanowi żadnego problemu, tak w przypadku hasła jest to nie lada wyzwanie.

Jednym z możliwych rozwiązań jest zastosowanie ukrytych pól tekstowych. Technika ta polega na wstawieniu bezpośrednio po polu typu password, pola tekstowego zawierającego domyślny tekst. Następnie przy pomocy JavaScript sterujemy widocznością hasła oraz maski.

<form id="formularz" method="post" action="">
	<div>
		<input type="text" name="login" id="login" value="Wpisz login" />
	</div>
	<div>
		<input type="password" name="password" id="password" style="display: none;" />
		<input type="text" name="password_mask" id="password_mask" value="Wpisz hasło" />
	</div>
	<div>
		<input type="submit" name="btn_signin" id="btn_signin" value="Zaloguj" />
	</div>
</form>

Dzięki jQuery całą podmianę można zmieścić zaledwie w kilku wierszach. Nic nie stoi na przeszkodzie, aby skorzystać z dowolnej biblioteki JavaScript lub nawet z “czystego” języka. Kod odpowiedzialny za ukrywanie/pokazywanie zaślepki wygląda następująco (w przykładzie pominąłem login).

$(document).ready(function() {
	$("#password_mask").focus(function() {
		$(this).hide();
		$("#password").show().focus();
	});

	$("#password").blur(function() {
		if($(this).val().length == 0) {
			$(this).hide();
			$("#password_mask").show();
		}
	});
});

Najpoważniejszą wadą zaprezentowanego rozwiązania jest jego podatność na błędy JavaScript. Dowolny błąd na stronie, np. związany ze statystykami lub innym zewnętrznym skryptem, spowoduje, że tak przygotowany formularz logowania niestety nie zadziała. Najlepszym zabezpieczeniem przed taką sytuacją jest wstrzyknięcie maskującego pola tekstowego oraz ukrycie pola typu password przez JavaScript. W ten sposób nawet w przypadku problemów z JavaScriptem, formularz logowania pozostanie sprawny. Ostatecznie cały kod będzie wyglądał przybierze następującą postać.

<form id="formularz" method="post" action="">
	<div>
		<input type="text" name="login" id="login" value="Wpisz login" />
	</div>
	<div>
		<input type="password" name="password" id="password" />
	</div>
	<div>
		<input type="submit" name="btn_signin" id="btn_signin" value="Zaloguj" />
	</div>
</form>
<script type="text/javascript">
$(document).ready(function() {
	$("<input type=\"text\" />")
		.attr("name", "password_mask")
		.attr("id", "password_mask")
		.val("Wpisz hasło")
		.insertAfter("#password");

	$("#password_mask").focus(function() {
		$(this).hide();
		$("#password").show().focus();
	});

	$("#password").hide().blur(function() {
		if($(this).val().length == 0) {
			$(this).hide();
			$("#password_mask").show();
		}
	});
});
</script>

Autor wpisu: batman, dodany: 04.02.2011 08:00, tagi: javascript, jquery

Przed kilkoma miesiącami na oficjalnym blogu jQuery pojawiła się informacja na temat powstania trzech nowych pluginów, które zostały zaakceptowane jako oficjalne rozszerzenia jQuery. Były to jQuery Templates, jQuery Data Link oraz jQuery Globalization. Według podanej wówczas informacji jQuery Templates miał trafić do głównej biblioteki jQuery wraz z pojawieniem się wersji 1.5. Najwyraźniej ekipa pracująca nad tym pluginiem nie zdążyła na czas i w wydanej kilka dni temu bibliotece, nie uraczymy szablonów. Nic nie stoi jednak na przeszkodzie, aby pobrać ten plugin osobno i już dzisiaj zacząć poznawanie jego możliwości.

Instalacja

Instalacja plginu jest tak samo banalna jak instalacja samego jQuery i sprowadza się do pobrania jego najnowszej wersji ze strony https://github.com/jquery/jquery-tmpl. Następnie wystarczy dołączyć plugin do strony.

Pierwszy szablon

Zanim zaczniemy zagłębiać się w szczegóły szablonów, rzućcie okiem na poniższy kod.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script src="jquery-1.5.min.js"></script>
		<script src="jquery.tmpl.min.js"></script>
		<script id="szablon" type="text/x-jquery-tmpl">
			<tr>
				<td>${nazwa}</td>
				<td>${cena}zł</td>
				<td><a href="/usun?id=${id}">usuń</a></td>
			</tr>
		</script>
		<script>
		$(document).ready(function() {
			var produkty = [
				{ id: 1, nazwa: "Spodnie", 	cena: "100" },
				{ id: 2, nazwa: "Buty", 	cena: "250" },
				{ id: 3, nazwa: "Okulary", 	cena: "90" },
				{ id: 4, nazwa: "Worek", 	cena: "1" }
			];

			$("#szablon").tmpl(produkty).appendTo("#produkty tbody");
		});
		</script>
	</head>
	<body>
		<table id="produkty">
			<thead>
				<tr>
					<th>Nazwa</th>
					<th>Cena</th>
					<th>Akcja</th>
				</tr>
			</thead>
			<tbody>
			</tbody>
		</table>
	</body>
</html>

To co widzicie to najprostszy przykład zastosowania szablonów jQuery. Wszystko sprowadza się do stworzenia szablonu HTML w znaczniku script, któremu nadajemy identyfikator (w tym przypadku identyfikatorem jest słowo szablon). Oprócz identyfikatora znacznik ten musi posiadać odpowiedni typ. Jest nim text/x-jquery-tmpl. W przypadku problemów z przeglądarkami, które nie będą poprawnie interpretować tego atrybutu można stosować text/html.

Tagi szablonów oraz nowe metody

W chwili obecnej do jQuery wprowadzone zostały następujące tagi.

  • ${} lub ${{= }} – służy do wstawiania do szablonu danych tekstowych
  • {{html }} – służy do wstawienia danych w postaci html
  • {{if}}, {{else}}, {{/if}} – podstawowa instrukcja warunkowa
  • {{each}} – pętla
  • {{tmpl}} – renderowanie szablonu w szablonie
  • {{wrap}} – możliwość opakowania jednego szablonu innym

Oprócz tagów, do jQuery wprowadzone zostały nowe funkcje. Są to:

  • .tmpl() – metoda wywoływana na szablonie. Przyjmuje dwa parametry – dane oraz opcje. Dane mogą zostać przekazane na dwa sposoby. W pierwszym z nich będzie to obiekt, którego klucze będą stanowić zmienne dostępne w szablonie. W drugim sposobie można przekazać tablicę obiektów. Wówczas szablon zostanie wyrenderowany tyle razy, ile elementów będzie miała tablica. Opcje służą do przekazania do szablonu dodatkowych danych. W wyniku działania tej metody uzyskamy kolekcję elementów, które możemy wstawić do drzewa DOM przy pomocy metod .appendTo, .prependTo, .insertBefore oraz .insertAfter.
  • jQuery.tmpl() – działa na podobnej zasadzie jak poprzednia metoda, z tą różnicą, że pierwszym argumentem jest treść szablonu, drugim dane, a trzecim opcje.
  • .tmplItem() oraz jQuery.tmplItem() – metody, dzięki którym uzyskamy dostęp do danych wyrenderowanego elementu na podstawie szablonu oraz wszystkich informacji powiązanych z tym elementem
  • .template() oraz jQuery.template() – metody te umożliwiają na “skompilowanie” szablonu do postaci nazwanego szablonu (named template), do którego możemy się odwoływać po jego nazwie.

Ponieważ w teorii wszystko zawsze wydaje się być bardziej skomplikowane niż to jest w rzeczywistości, przejdźmy do przykładów.

${}

W miejsce tego taga wstawiona zostanie zawartość przypisana pod klucz obiektu przekazanego jako dane do szablonu.

<script id="szablon" type="text/x-jquery-tmpl">
	<p>${pole}</p>
</script>
<script>
$(document).ready(function() {
	$("#szablon").tmpl({ pole: "zawartosc"}).appendTo("#element");
});
</script>
<div id="element"></div>

Zamiast ${pole} możemy napisać {{= pole}} i efekt będzie identyczny.

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.