<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>m1chu.eu - another devblog &#187; Prototype</title>
	<atom:link href="http://m1chu.eu/category/webmastering/client-side/prototype/feed/" rel="self" type="application/rss+xml" />
	<link>http://m1chu.eu</link>
	<description>we live, as we dream... alone - another devblog</description>
	<lastBuildDate>Sun, 14 Nov 2010 11:07:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Efekt graficznego podświetlenia w jQuery i Prototype z Scriptaculous</title>
		<link>http://m1chu.eu/2009/02/09/efekt-graficznego-podswietlenia-w-jquery-i-prototype-z-scriptaculous/</link>
		<comments>http://m1chu.eu/2009/02/09/efekt-graficznego-podswietlenia-w-jquery-i-prototype-z-scriptaculous/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 12:45:54 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[(x)HTML]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[highlighter]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[podświetlenie]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[scriptaculous]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=1157</guid>
		<description><![CDATA[Jedni nie korzystają z nich wcale, niektórzy tylko po to aby zwiększyć funkcjonalność tworzonych przez siebie stron, a u jeszcze innych zauważalny jest przepych tego typu rozwiązań. Biblioteki programistyczne języka JavaScript, bo o ich wykorzystaniu tu mowa to źródło bardzo różnorodnych, nie tylko funkcjonalnych, ale także estetycznych efektów. Sieć aż kipi od dobrych i słabych, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="iborder" src="http://farm1.static.flickr.com/242/3264023222_981cfd8fd0_o.png" alt="Efekt podświetlania w jQuery i Prototype" style="height: 119px;" /></p>
<p>Jedni nie korzystają z nich wcale, niektórzy tylko po to aby zwiększyć funkcjonalność tworzonych przez siebie stron, a u jeszcze innych zauważalny jest przepych tego typu rozwiązań. Biblioteki programistyczne języka JavaScript, bo o ich wykorzystaniu tu mowa to źródło bardzo różnorodnych, nie tylko funkcjonalnych, ale także estetycznych efektów. Sieć aż kipi od dobrych i słabych, lepiej oraz słabiej wytłumaczonych przykładów użycia możliwości <a target="_blank" href="http://mootools.net/"  title="MooTools">MooTools</a>, <a target="_blank" href="http://jquery.com/"  title="jQuery">jQuery</a>, <a target="_blank" href="http://www.prototypejs.org/"  title="Prototype">Prototype</a> z <a target="_blank" href="http://script.aculo.us/"  title="Scriptaculous">Scriptaculous</a>, czy innych mniej powszechnych frameworków.</p>
<p>Jednym z takich efektów jest możliwość stworzenia animowanego, graficznego podświetlenia pojawiającego się np. nad grafiką wywołującą animację. Interaktywność taka została opisana na <a target="_blank" href="http://utnij.eu/product-highlighter-mootools/"  title="Product highlighter with MooTools">NetTuts</a> z wykorzystaniem MooTools. My osiągniemy taki wynik dzięki zastosowaniu jQuery (w jednym przykładzie) oraz dodatkowo także za pomocą Prototype wraz z Scriptaculous (w drugim przykładzie).</p>
<p><span id="more-1157"></span></p>
<p style="text-align: center; font-size: 10px;"><object type="application/x-shockwave-flash" width="538" height="352" data="http://www.vimeo.com/moogaloop.swf?clip_id=3136566&amp;server=www.vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=01AAEA"><param name="quality" value="best" /><param name="allowfullscreen" value="true" /><param name="scale" value="showAll" /><param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=3136566&amp;server=www.vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=0&amp;show_portrait=0&amp;color=01AAEA" /><img class="iborder" src="http://farm1.static.flickr.com/190/3263308689_e6578263b5_o.png" alt="Oczekiwany efekt" style="height: 366px;" /></object><br />Oczekiwany efekt.</p>
<h2>Krok 1: Za co się chwycić na początku&#8230;</h2>
<p>Na początek musisz wiedzieć w jakim celu potrzebny jest Ci prezentowany w tym artykule efekt. Menu? Wyświetlanie dodatkowych informacji w graficznej liście produktów? Czy może szybki, animowany splash? Wybór jest Twój i podług niego będziesz musiał zaopatrzyć się w dodatkowe, niezbędne elementy do wykonania podświetlenia.</p>
<p>Chodzi tu mianowicie o grafiki, których musi być dwa razy więcej niż elementów podatnych na działanie mechanizmu. Powiedzmy, jeżeli chcemy w pięcioelementowym menu zastosować w każdym zdarzenie po najechaniu myszką zgodne z przesłaniem tego artykułu to potrzebujemy dziesięciu grafik. Pięć opisujących przyciski menu i drugie tyle będące &#8222;treścią&#8221; pojawiającą się po podświetleniu.</p>
<p>Po uporaniu się z wizualną częścią problemu oraz strony internetowej możemy ruszyć krok dalej.</p>
<h2>Krok 2: Zaopatrujemy się w jQuery i/lub Prototype i Scriptaculous!</h2>
<p><strong>jQuery</strong> to aktualnie najpopularniejsza biblioteka. I najłatwiej ją skatalogować w czeluścia własnego projektu. Wystarczy ze <a target="_blank" href="http://jquery.com/"  title="jQuery">strony głównej</a> pobrać wersję <strong>1.3.1 production/Minified</strong> i umieścić ją w obrębie plików tworzonego przez nas przykładu (niezbędny będzie tylko plik <strong>jquery-1.3.1.min.js</strong>).</p>
<p>Z <strong>Prototype</strong> sprawa jest ciut bardziej skomplikowana, bo prócz standardowego frameworka musimy pobrać także dodatkowy interfejs w postaci <strong>Scriptaculous</strong>, dzięki któremu uzyskamy dostęp do efektu pozwalającego na dynamiczne zmienianie właściwości CSS elementów strony. Ściągamy więc <a target="_blank" href="http://utnij.eu/prototype-download/"  title="Prototype">wersję 1.6.0.3 pierwszej biblioteki</a>, oraz paczkę z <a target="_blank" href="http://utnij.eu/scriptaculous-download/"  title="Scriptaculous">wersją 1.8.2 drugiej</a>. Z obydwu wyodrębniamy pliki i w ramach folderu tworzonego przez nas projektu umieszczamy tylko <strong>prototype.js</strong> oraz <strong>effects.js</strong> (z drugiego archiwum).</p>
<p>W przypadku tego artykułu umownie pliki związane z frameworkami będą znajdować się w podkatalogu <strong>javascript</strong> folderu głównego. Obydwa przykłady (dotyczące, jeden <strong>jQuery</strong>, a drugi <strong>Prototype z Scriptaculous</strong>) będą oczywiście wykonywane w osobnych plikach znajdujących się w dwóch różnych katalogach.</p>
<p style="text-align: center; font-size: 10px;"><img class="iborder" src="http://farm1.static.flickr.com/243/3263426717_b9e39151ce_o.png" alt="Rozdzielenie implementacji przykładów na dwa katalogi" style="height: 280px;" /><br />Przykładowe rozdzielenie implementacji przykładów na dwa katalogi. W naszym przypadku pliki <strong>.js</strong> znajdują się dodatkowo w podkatalogu <strong>javascript</strong>.</p>
<h2>Krok 3: Tworzymy strukturę XHTML</h2>
<p>Atutem naszego rozwiązania jest kompatybilność z serwowaniem dokumentu XHTML w postaci <code>application/xhtml+xml</code>, czego bardzo często brakuje w przypadku efektów opartych na bibliotekach JS. Z racji tego także, że i w przypadku <strong>Prototype</strong> i <strong>jQuery</strong> struktura strony pozostaje niezmienna to obojętnie który framework wykorzystujesz poniższe tłumaczenie i partie kodu będą prawidłowe.</p>
<p>Z powodu tego w jaki sposób będziemy wysyłać treść strony posłużymy się małą częścią kodu PHP, a co za tym idzie plik korzystający z naszego mechanizmu musi mieć też takie rozszerzenie (no chyba, że serwer jest inaczej skonfigurowany, ale to już problematyka do rozwiązania na inny temat).</p>
<pre class="brush: php; title: ;">&lt;?php
if ( stristr($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') ) // jeżeli przeglądarka obsługuje application/xhtml+xml
{
	header(&quot;Content-Type: application/xhtml+xml; charset=utf-8&quot;); // wysłanie odpowiednich nagłówków
	print '&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;'.&quot;\r\n&quot;;
	print '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.1//EN&quot;'.&quot;\r\n&quot;;
	print '&quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&quot;&gt;'.&quot;\r\n&quot;;
}
else // wysłanie dokumentu jako text/html dla przeglądarek nie obsługujących typu zawartości pliku z powyższego warunku, np. dla IE
{
	header(&quot;Content-Type: text/html; charset=utf-8&quot;);
	print '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;'.&quot;\r\n&quot;;
	print '&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;'.&quot;\r\n&quot;;
}
?&gt;</pre>
<p>Poniżej dodajemy uniwersalny układ strony. Ważnym ułatwieniem jest możliwość tworzenia odnośników z elementów graficznych podatnych mechanizmowi, a także fakt, że nie korzystamy w nim z tagów <code>img</code>, a efektu zbliżonego do <a href="http://m1chu.eu/webmastering/efekt-rollover-w-css-bez-przeladowywania-obrazka"  title="Efekt rollover">sliding-doors</a> w celu wyświetlania obrazów.</p>
<pre class="brush: xml; title: ;">&lt;html lang=&quot;pl&quot; xml:lang=&quot;pl&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-type&quot; content=&quot;&lt;?php print ( stristr($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') ? 'application/xhtml+xml' : 'text/html' ); // typ zawartości zależny do możliwości przeglądarki użytkownika ?&gt;; charset=utf-8&quot; /&gt;
  	&lt;meta name=&quot;Description&quot; content=&quot;Product highlighter - tworzenie dynamicznych opisów produktów - m1chu.eu&quot; /&gt;
  	&lt;meta name=&quot;Keywords&quot; content=&quot;product, highlighter&quot; /&gt;
	&lt;title&gt;Product highlighter&lt;/title&gt;
	&lt;style type=&quot;text/css&quot;&gt;@import url('stylesheet.css');&lt;/style&gt; &lt;!-- arkusz stylów --&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;div id=&quot;siteContainer&quot;&gt;
		&lt;div id=&quot;highlightsContainer&quot;&gt; &lt;!-- zbiór grafik wyświetlanych przy najechaniu kursorem --&gt;
			&lt;div class=&quot;highlights&quot; id=&quot;highlight1&quot;&gt;&lt;/div&gt;
			&lt;div class=&quot;highlights&quot; id=&quot;highlight2&quot;&gt;&lt;/div&gt;
			&lt;div class=&quot;highlights&quot; id=&quot;highlight3&quot;&gt;&lt;/div&gt;
		&lt;/div&gt;

		&lt;div id=&quot;pageContainer&quot;&gt; &lt;!-- zbiór grafik podatnych na efekt --&gt;
			&lt;div class=&quot;pages&quot; id=&quot;page1&quot;&gt;&lt;a href=&quot;http://m1chu.eu/&quot;&gt;&lt;/a&gt;&lt;/div&gt;
			&lt;div class=&quot;pages&quot; id=&quot;page2&quot;&gt;&lt;a href=&quot;http://vivee.info/&quot;&gt;&lt;/a&gt;&lt;/div&gt;
			&lt;div class=&quot;pages&quot; id=&quot;page3&quot;&gt;&lt;a href=&quot;http://utnij.eu/&quot;&gt;&lt;/a&gt;&lt;/div&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h2>Krok 4: Stylizujemy strukturę strony za pomocą CSS</h2>
<p>Posługując się metodami <a href="http://m1chu.eu/2009/01/08/pozycjonujemy-za-pomoca-kaskadowego-arkusza-stylow-css/"  title="Pozycjonowanie za pomocą CSS">pozycjonowania elementów</a> dostępnymi w kaskadowym arkuszu stylów możemy operując na elementach o identyfikatorach <code>siteContainer</code>, <code>pageContainer</code>, <code>highlightsContainer</code> oraz <code>divach</code> potomnych ułożyć i wystylizować wygląd, w tym położenie jak na wyżej zamieszczonym filmiku (screenie) obrazującym wykonanie zadania z tego artykułu.</p>
<p>Do wszystkich bloków kodu CSS odwołujących się do tagów zawierających identyfikatory grafik zostały dodane także właściwości <code>background</code> z adresem pliku tła.</p>
<p>W naszym przypadku poniższy kod zapisujemy do pliku <strong>stylesheet.css</strong>.</p>
<pre class="brush: css; title: ;">/* ustawienia domyślne dla ciała strony (w poprawnie wysyłanym XHTML jest to html+body, a nie tylko body) */
html, body {
	margin: 0px;
	padding: 0px;
	background: #000 url('bg.png') repeat-x;
}

#siteContainer {
	margin: 150px auto 0px auto; /* marginesy - wyśrodkowanie poziome */
	width: 573px;
	height: 345px;
	position: relative; /* relatywna pozycja, kontener */
	background: transparent url('container.png') no-repeat top left;
}
#pageContainer {
	position: absolute; /* pozycja względem #siteContainer */
	z-index: 5; /* ponad ciałem strony i pod #highlightsContainer */
	top: 128px;
	left: 0px;
}
#highlightsContainer {
	position: absolute; /* pozycja względem #siteContainer */
	z-index: 10; /* ponad pozostałymi elementami */
	left: 178px;
	top: 30px;
}
/* ustawienie w linii wraz z zmianą wyglądu kursora */
#pageContainer &gt; div {
	float: left;
	cursor: pointer;
}
/* rozmiary klikalnych divów potomnych znajdujących się w kontenerze listy grafik podatnych na działanie mechanizmu */
#pageContainer &gt; div a {
	width: 178px;
	height: 178px;
	display: block;
}
#page1 {
	margin-right: 19px; /* prawy margines - odstęp od kolejnego diva */
}
#page1 a {
	background: url('icon_1.png') no-repeat; /* tło grafiki podatnej na działanie efektu */
}
#page2 {
	margin-right: 20px; /* prawy margines - odstęp od kolejnego diva */
}
#page2 a {
	background: url('icon_2.png') no-repeat; /* tło grafiki podatnej na działanie efektu */
}
#page3 a {
	background: url('icon_3.png') no-repeat; /* tło grafiki podatnej na działanie efektu */
}

/* rozmiary wszystkich potomków typu div kontenera zawierającego podświetlenia */
#highlightsContainer &gt; div {
	position: absolute;
	width: 222px;
	height: 101px;
	display: block;
}
/* pliki tła w pojawiających się podświetleniach */
#highlight1 {
	background: transparent url('highlights_1.png') no-repeat;
}
#highlight2 {
	background: transparent url('highlights_2.png') no-repeat;
}
#highlight3 {
	background: transparent url('highlights_3.png') no-repeat;
}</pre>
<h2>Krok 5a: Dodajemy jQuery do dokumentu</h2>
<p>Tego, czego zabrakło dotychczasowo w naszym dokumencie to załączenie bibliotek oraz pliku <strong>.js</strong> w którym będzie znajdować się kod animujący pożądany przez nas efekt.</p>
<p>Dla <strong>jQuery</strong> w sekcji <code>head</code> należy dodać pliki <strong>jquery-1.3.1.min.js</strong> oraz <strong>product-highlighter.js</strong> (który umownie będzie zawierał dodatkowy kod).</p>
<pre class="brush: xml; title: ;">	&lt;script type=&quot;text/javascript&quot; src=&quot;javascript/jquery-1.3.1.min.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;javascript/product-highlighter.js&quot;&gt;&lt;/script&gt;</pre>
<h2>Krok 5b: Dodajemy Prototype z Scriptaculous do dokumentu</h2>
<p>Tym razem musimy dodać jeden plik więcej. Bibliotekę (<strong>prototype.js</strong>), jej dodatkowy interfejs, a dokładniej plik zawierający obiekt <strong>Effect</strong> (<strong>effects.js</strong>) oraz jak w powyższym przypadku plik z naszym kodem animacji (<strong>product-highlighter.js</strong>).</p>
<pre class="brush: xml; title: ;">		&lt;script type=&quot;text/javascript&quot; src=&quot;javascript/prototype.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;javascript/effects.js&quot;&gt;&lt;/script&gt;
	&lt;script type=&quot;text/javascript&quot; src=&quot;javascript/product-highlighter.js&quot;&gt;&lt;/script&gt;</pre>
<h2>Krok 6a: Implementujemy kod animacji z użyciem jQuery</h2>
<p>Jak to bywa w przypadku tego frameworka, aby jakieś zdarzenie działało poprawnie powinno się je umieszczać w funkcji <code>$(document).ready()</code>, której zawartość zostanie załadowana w momencie załadowania drzewa dokumentu.</p>
<pre class="brush: jscript; title: ;">$(document).ready(function() {
	[kod]
});</pre>
<p>W <strong>[</strong><strong>kod]</strong> musimy przypisać (do tablicy) wg. klasy wszystkie grafiki wyświetlane podczas podświetlenia, ustawić parametry podstawowe CSS oraz stworzyć sprawdzanie w pętli, czy dana grafika o klasie <code>.pages</code> nie jest najechana przez kursor i w zależności o danego trybu (<em>kursor na/kursor poza</em>) wykonać pożądaną animacji (<em>wyłonienie dodatkowego tła / zanikanie dodatkowego tła</em>).</p>
<p>Poniższy kod umieszczamy w pliku <strong>product-highlighter.js</strong>.</p>
<pre class="brush: jscript; title: ;">$(document).ready(function() {
	// tablica elementów o klasie .highlights
	var highlights = $('.highlights');

	// ustawienie pełnej przezroczystości elementów pojawiających się w czasie najechania myszką na obiekty podatne efektowi oraz widzialności ich kontenera
	$('.highlights').css('opacity', 0);
	$('#highlightsContainer').css('visibility', 'visible');

	// sprawdzanie każdego elementu podatnego mechanizmowi
	$('.pages').each(function(i) {
		// jeżeli na danym elemencie znajduje się kursor
		$(this).mouseover(function() {
			// wykonanie animacji grafiki wyłanianej i przypisanej do najechanego elementu (margines o 15px w górę i brak przezroczystości w czasie 0,5 sekundy)
			$(highlights[i]).animate({
				opacity: 1,
				marginTop: '-15px'
			}, 500);
		}).mouseout(function(){ // jeżeli na danym elemencie nie znajduje się już kursor
			$(highlights[i]).animate({
				opacity: 0,
				marginTop: '-0px'
			}, 500);
		});
	});
});</pre>
<p>Należy jeszcze wyjaśnić dokładniej w jaki sposób działa <code>$(highlights[i]).animate()</code>. Mianowicie przy każdej iteracji pętli <code>$('.pages').each()</code> przekazuje ona do parametru <code>function(i)</code> aktualny numer elementu na którym się znajduje. Ponieważ w id <code>pageContainer</code> znaczniki potomne muszą być posegregowane i musi być ich tyle samo co obiektów graficznych w <code>highlightsContainer</code> to jeżeli kursor znajduje się na pierwszym podatnym na efekt obrazie to w podświetleniu wyłania się także pierwsza grafika. Wszystko to dzięki wyłuskaniu jej z tablicy <code>highlights</code> poprzez parametr <code>i</code>.</p>
<h2>Krok 6b: Implementujemy kod animacji z użyciem Prototype z Scriptaculous</h2>
<div class="explain"><code>Event.observe</code> &#8211; uchwyt rejestrujący zdarzenie na drzewie dokumentu. Funkcja obiektu składającego się na bibliotekę <strong>Prototype</strong>. Posiada cztery argumenty:
<ul>
<li><strong>element</strong> &#8211; obserwowany element DOM, mogący być referencją do niego bądź jego identyfikatorem,</li>
<li><strong>nazwaZdarzenia</strong> &#8211; standaryzowana wg. <a target="_blank" href="http://utnij.eu/af/"  title="DOM Level 2 Events">DOM Level 2 Events</a> nazwa zdarzenia, np. <strong>load</strong>,</li>
<li><strong>uchwyt</strong> &#8211; uchwyt w postaci funkcji.</li>
</ul>
<p>Przykład:</p>
<pre class="brush: xml; title: ;">&lt;p id=&quot;test&quot;&gt;Prototype&lt;/p&gt;</pre>
<pre class="brush: jscript; title: ;">Event.observe('test', 'click', function() {
	[kod]
});</pre>
</div>
<p>Podobnie w <strong>Prototype</strong> obserwujemy zdarzenie, ale tym razem załadowania całej strony w celu późniejszej obserwacji aktywności kursora na wybranych elementach aktywnych. Można oczywiście podobnie jak w poprzednim podpunkcie wykonać obserwacje zdarzeń wraz z załadowanie DOM (drzewa dokumentu) poprzez użycie <code>document.observe('dom:loaded', function() {})</code>. To tylko kwestia osobistego wyboru.</p>
<pre class="brush: jscript; title: ;">Event.observe(window, 'load', function() {
	[kod]
});</pre>
<p>Dalsze postępowanie jest adekwatne do tego opisanego w przypadku zastosowania <strong>jQuery</strong>. Z tymże, tablicę elementów o danej klasie pobiera się poprzez podwójny znak dolara (<code>$$</code>), a najechanie oraz zjechanie kursorem poza zadany obszar rozpoznaje się także poprzez obiekt <code>Event</code> i metodę <code>observe()</code>. Do animacji służy funkcja <code>Morph</code> instancji <code>Effect</code> z pliku <code>effects.js</code> interfejsu <strong>Scriptaculous</strong >.</p>
<pre class="brush: jscript; title: ;">Event.observe(window, 'load', function() {
	var highlights = $$('.highlights'); // utworzenie tablicy

	$$('.highlights').invoke('setStyle', { opacity: 0 }); // ustawienie stylu przezroczystości
	$$('#highlightsContainer').invoke('setStyle', { visibility: 'visible' }); // widzialność kontenera

	$$('.pages').each(function(v, i) { // pętla
		Event.observe(v, 'mouseover', function() { // zdarzenie wykonywane w momencie pojawienia się kursora na elemencie
			new Effect.Morph(highlights[i], { // animacja
				style: 'opacity: 1; margin-top: -15px;',
				duration: 0.5 // czas 0,5 sekundy
			});
		});
		Event.observe(v, 'mouseout', function() { // zdarzenie wykonywane w momencie wyjechania kursorem poza element
			new Effect.Morph(highlights[i], {
				style: 'opacity: 0; margin-top: 0px;',
				duration: 0.5
			});
		});
	});
});</pre>
<p>Tym razem do funkcji w <code>$$('.pages').each()</code> przekazywane są dwa parametry: <code>v</code> i <code>i</code>. Pierwszy z nich jest odpowiednikiem <code>this</code> i wskazuje na aktualnie przetwarzany element tablicy znaczników o klasie <code>.pages</code>. Drugi to numer pokazujący który z kolei tag jest aktualnie sprawdzany. Inaczej pisząc jego zadanie jest równoznaczne do działania parametru <code>i</code> w przykładzie z <strong>jQuery</strong>.</p>
<div class="explain"><code>Effect.Morph</code> &#8211; metoda interfejsu <code>Scriptaculous</code> >= <strong>1.7</strong>. Pozwala na animacyjną zmianę właściwości CSS elementu. Przyjmuje jeden podstawowy argument <code>style</code> zawierający w sobie właściwości i wartości CSS w formie oryginalnej bądź w postaci <strong>Camel-Case</strong>, czyli bez spacji i znaków specjalnych pomiędzy kilkoma członami nazwy właściwości. Opcjonalnie można dodawać kolejne parametry rdzenia obiektu <code>Effect</code>, takie jak <code>duration</code> (czas animacji), czy <code>transition</code> (rodzaj animacji, wymaga <code>Effect.Transitions</code>).</p>
<p>Przykład:</p>
<pre class="brush: jscript; title: ;">new Effect.Morph('div_id', {
	style: {
		background-color: '#000',
		color: '#fff'
	},
	duration: 0.5,
	transition: Effect.Transitions.spring
});</pre>
</div>
<h2>Demonstracja wyników&#8230;</h2>
<p>Stworzyłem dwa gotowe przykłady, których analiza pozwoli Wam jeszcze bardziej zrozumieć jak stworzyć ten efekt. <a href="http://use.m1chu.eu/-jquery/product-highlighter/"  title="Product Highlighter - jQuery"><strong>Pierwszy</strong></a>, za pomocą jQuery. <a href="http://use.m1chu.eu/-prototype/product-highlighter/"  title="Product Highlighter - Prototype z Scriptaculous"><strong>Drugi</strong></a>, za pomocą Prototype z Scriptaculous.</p>
<p>Jeżeli chcecie dowiedzieć się więcej o tych bibliotekach to zapraszam do ich dokumentacji (<a target="_blank" href="http://www.prototypejs.org/api"  title="API Prototype">Prototype</a>, <a target="_blank" href="http://docs.jquery.com/Main_Page"  title="API jQuery">jQuery</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2009/02/09/efekt-graficznego-podswietlenia-w-jquery-i-prototype-z-scriptaculous/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Kolizje współdziałania bibliotek JavaScript na podstawie wtyczek WordPress&#8230;</title>
		<link>http://m1chu.eu/2008/10/02/kolizje-wspoldzialania-bibliotek-javascript-na-podstawie-wtyczek-wordpress/</link>
		<comments>http://m1chu.eu/2008/10/02/kolizje-wspoldzialania-bibliotek-javascript-na-podstawie-wtyczek-wordpress/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 10:45:38 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[biblioteka]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[wtyczka]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=96</guid>
		<description><![CDATA[Coraz więcej różnorodnych stron internetowych korzysta z techniki która w szeroki sposób pozwoliła rozwinąć się przede wszystkim JavaScriptowi &#8211; z Ajaxa. Podobnie jest z różnorodnymi wtyczkami do systemu blogów WordPress. Z reguły korzystają one jednak z jakiejś biblioteki JavaScript zbierającej w całość jego najważniejsze funkcje i pozwalającej na ich prostsze użycie. W momencie jednak, kiedy [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="iborder" src="http://farm4.static.flickr.com/3066/2953934393_d684ed0058_o.png" alt="Współdziałanie framework'ów na przykładzie WordPress'a" /></p>
<p>Coraz więcej różnorodnych stron internetowych korzysta z techniki która w szeroki sposób pozwoliła rozwinąć się przede wszystkim JavaScriptowi &#8211; z Ajaxa. Podobnie jest z różnorodnymi wtyczkami do systemu blogów <a target="_blank" href="http://wordpress.org/"  title="WordPress">WordPress</a>. Z reguły korzystają one jednak z jakiejś biblioteki JavaScript zbierającej w całość jego najważniejsze funkcje i pozwalającej na ich prostsze użycie. W momencie jednak, kiedy w naszych pluginach pojawi się w użyciu kilka wtyczek możemy napotkać problem kolizji ich współdziałania.</p>
<p><span id="more-96"></span></p>
<h2>Prolog!</h2>
<p>Zanim zacznę muszę wspomnieć, że kolizja opisywana poniżej może występować na jakiejkolwiek stronie, a opisywana przeze mnie sytuacja jest tylko przykładem. Nie mniej jednak mankament ten postaram się wytłumaczyć na podstawie jednoczesnego działania <a target="_blank" href="http://utnij.eu/ajax-comments/"  title="WP Ajax Comments">AJAX Comments</a> i przystosowanej do personalnych potrzeb modyfikacji zakładek (przykładem są te umieszczone z lewej strony tego wpisu). Pierwsza wtyczka domyślnie używa <a target="_blank" href="http://script.aculo.us/"  title="Script.Aculo.Us">Script.Aculo.Us</a>, a co za tym idzie także frameworku <a target="_blank" href="http://www.prototypejs.org/"  title="Prototype">Prototype</a>. W drugim wypadku oprę się o <a target="_blank" href="http://vivee.info/2008/08/05/zakladki-do-sidebara/"  title="Zakładki do Sidebara">kurs tworzenia zakładek</a> w WP <strong>palmiaka</strong>, który używa za to <a target="_blank" href="http://jquery.com/"  title="jQuery">jQuery</a>.</p>
<p>Po poprawnej instalacji obydwu modyfikacji pewnie spora część z Was nie dostrzeże dręczącego nas feleru. Dlaczego? Gdyż na stronie głównej wszystko będzie działało prawidłowo, ale bynajmniej nie na podstronach w których będzie możliwe komentowanie wpisów. Dla przykładu w momencie wczytania najpierw <strong>prototype.js</strong> i <strong>scriptaculous.js</strong>, a później <strong>jquery.js</strong> stworzone przez nas zakładki nie będą poprawnie działać (nie zostaną one ukryte i nie będzie możliwości przejścia pomiędzy nimi). Dlaczego tak się dzieje? Tutaj należałoby poruszyć pewną sprawę dotyczącą samego działania frameworków tego typu.</p>
<h2>Funkcja $(argumenty)</h2>
<p>Między innymi do tworzenia obiektu danej biblioteki używa się funkcji <code>$(argumenty);</code>. Dzięki temu operujące np. na obiektach DOM, czy tablicach frameworki dzięki tej specjalnej konstrukcji pozwalają użytkownikowi na wykorzystywanie ich konkretnych funkcji.</p>
<p style="text-align: center;"><a target="_blank" href="http://farm4.static.flickr.com/3155/2905203185_36c209390b_o.png"  title="Powiększenie" class="lightbox"><img src="http://farm4.static.flickr.com/3155/2905203185_1e8236bb72.jpg" alt="Różnorodne metody korzystania z elementów strony" /></a></p>
<h2>Problematyka korzystania z więcej niż jednej biblioteki naraz&#8230;</h2>
<p>W momencie kiedy w skrypcie korzystamy z dwóch lub większej ilości frameworków może nastąpić kolizja w ich działaniu. W uproszczeniu przez użycie <code>$();</code> w każdej z nich. I tak to w naszym przykładzie funkcje, czy odwołania do obiektów które powinny być wykonane za pomocą <strong>jQuery</strong> zostaną wykonane przez pierwszą wczytaną klasę. A wszystko przez to, że każda z podanych bibliotek odwołuje się do danego elementu w taki sam sposób.</p>
<h2>Solucja!</h2>
<p>Na szczęście od wersji <strong>1.1.4</strong> z pomocą przychodzą nam developerzy <strong>jQuery</strong> wraz z funkcją pozwalającą na interoperacyjność &#8211; <code>jQuery.noConflict(param);</code>.</p>
<pre class="brush: jscript; title: ;">jQuery.noConflict(); // zwraca kontrolę nad $ bibliotece domyślnej (wcześniej używanej)
jQuery.noConflict(true); // zwraca kontrolę nad $ i jQuery (którego $ jest aliasem) oryginalnemu właścicielowi - należy używać z ostrożnością!</pre>
<p>Co należy wiedzieć w kwestii używania tego to przede wszystkim fakt, że wymaga się, aby powyższą funkcję wywołać przed użyciem elementów innych bibliotek, a także <strong>jQuery</strong> powinno być wczytywane po pozostałych frameworkach. W konkretnym wypadku związanym z WP który opisujemy należy także domyślnie dostarczone niżej wymienione biblioteki uaktualnić. Niestety w opisywanych tutaj wtyczkach i systemie blogów są to wersje starsze i przedstawiony trick w tym artykule nie zadziała dopóki nie ściągniemy zaktualizowanych wersji frameworków.</p>
<pre class="brush: jscript; title: ;">&lt;script type=&quot;text/javascript&quot; src=&quot;libs/prototype.js&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;libs/scriptaculous.js&quot; /&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;libs/jquery.js&quot; /&gt;</pre>
<p>Domyślnie także należy używać w tym trybie <strong>jQuery</strong> zamiast <strong>$</strong>.</p>
<pre class="brush: jscript; title: ;">jQuery.noConflict();
jQuery(&quot;p&quot;).hide(); // użycie frameworka jQuery
$(&quot;div&quot;).style.display = 'none'; // użycie innego frameworka, np. prototype</pre>
<p>Ponieważ oczywiście zaprezentowana funkcja jest podatna na przypisywanie do zmiennych to niekoniecznie musimy używać standardowej, dłuższej nazwy. Negatywem tego rozwiązania jest jednak potencjalny konflikt nazw w przypadku pisania aplikacji internetowej przez wielu programistów.</p>
<pre class="brush: jscript; title: ;">var q = jQuery.noConflict();
q(&quot;p&quot;).hide();
$(&quot;div&quot;).style.display = 'none';</pre>
<p>Ostatecznie moglibyście także spytać <strong>&#8222;co zrobić, aby móc wewnątrz bloku kodu używać $ dla jQuery?&#8221;</strong>. Wystarczy poprzedzić zadaną funkcję przez <code>jQuery</code>, bądź zakończyć poprzez <code>(jQuery)</code>.</p>
<pre class="brush: jscript; title: ;">jQuery(function($) { [...] }); // wersja pierwsza
(function($) { [...] })(jQuery); // wersja druga</pre>
<p>Niestety w takim wypadku wewnątrz powyższych bloków kodu nie ma możliwości odniesienia się do obiektów innych bibliotek.</p>
<h2>Przykład pozwalający na prawidłowe działanie wspomnianych zakładek&#8230;</h2>
<p>Poprawiony przykład z <strong>vivee</strong>, który należy użyć w wypadku w.w. konfliktu (kod JavaScript).</p>
<pre class="brush: jscript; title: ;">jQuery.noConflict();

function tabs(id) {
	jQuery(&quot;#&quot;+id+&quot; h2:first a&quot;).addClass(&quot;active&quot;);
    jQuery(&quot;#&quot;+id+&quot; div&quot;).not(&quot;:first&quot;).hide();

    jQuery(&quot;#&quot;+id+&quot; h2 a&quot;).click(function() {
    	var licznik = jQuery(&quot;#&quot;+id+&quot; h2 *&quot;).index(this);                                             

        jQuery(&quot;#&quot;+id+&quot; h2 a&quot;).removeClass(&quot;active&quot;);
        jQuery(this).addClass(&quot;active&quot;);
        jQuery(&quot;#&quot;+id+&quot; div:visible&quot;).hide();

        jQuery(&quot;#&quot;+id+&quot; div&quot;).eq(licznik).show();
        return false;
    });
}

jQuery(document).ready(function(){
    tabs(&quot;zakladki&quot;);
});</pre>
<h2>Epilog&#8230;</h2>
<p><strong>WPNinja</strong> na swoim blogu poświęconym WordPressowi prawidłowo stwierdził w stosunku do mojej osoby, że mieszanie bibliotek nie jest dobrym zwyczajem.</p>
<pre class="brush: plain; title: ;">&quot;@m1chu,
Mieszanie ze sobą bibliotek to masakra. Nie dość, że zajmuje to niemiłosiernie dużo miejsca to, jak zauważyłeś w swoim artykule, może powodować konflikty.&quot;</pre>
<p>Opisany przeze mnie artykuł powinien być stosowany tylko w wyjątkowych sytuacjach. Należy z reguły <strong>unikać</strong> użytkowania kilku frameworków naraz, bo to obciąża w znacznym stopniu skrypt poprzez ich wagę, a co za tym idzie ilością danych do załadowania. Zdaję sobie jednak sprawę, że niekiedy jest to niezmiernie trudne (czego jak na razie w fazie rozwojowej przykładem jest mój blog ;]). Podziękowania za przypomnienie dla <strong>WPNinja&#8217;y</strong> o tym, że zapomniałem tak ważnego faktu umieścić w swoich wpisie.</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2008/10/02/kolizje-wspoldzialania-bibliotek-javascript-na-podstawie-wtyczek-wordpress/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

