<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><title>Dziudek's jogger</title><link>http://blog.dziudek.pl/</link><description>Wpisy z dziennika internetowego Jogger, wspomaganego przez Jabbera</description><lastBuildDate>Thu, 18 Mar 2010 17:35:25 +0100</lastBuildDate><generator>JoggerPL</generator><item><title>joomla.jogger.pl</title><link>http://blog.dziudek.pl/2010/02/15/joomla-jogger-pl/</link><description>&lt;p&gt;Jeżeli komuś tematyka związana z CMS-em Joomla! jest bliska to zapraszam na swój nowy blog pod adresem:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://joomla.jogger.pl/&quot;&gt;joomla.jogger.pl/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Zapewne wpisy będą się na nim częściej pojawiać niż tutaj ;)&lt;/p&gt;
</description><pubDate>Mon, 15 Feb 2010 00:20:13 +0100</pubDate><guid>http://blog.dziudek.pl/2010/02/15/joomla-jogger-pl/</guid><category>Ogólne</category></item><item><title>HTC vs. iPhone</title><link>http://blog.dziudek.pl/2009/12/28/htc-vs-iphone/</link><description>&lt;p&gt;Przeszło miesiąc temu wyposażyłem się w iPhone 3GS. Wcześniej przez półtora roku korzystałem z HTC Touch Diamond i korzystając z tej okazji przygotowałem swego rodzaju porównanie tych telefonów. Oba telefony w momencie zakupu znajdowały się w podobnym przedziale cenowym jeżeli chodzi o cenę aparatu bez abonamentu &lt;sup&gt;[1]&lt;/sup&gt; - w wypadku iPhone uzbroiłem się w abonament gdyż bez mobilnego dostępu do Internetu ten telefon nie ma racji bytu (jak zresztą chyba wszystkie nowsze telefony).&lt;/p&gt;
&lt;p&gt;Muszę przyznać, że dość długo rozważałem ten zakup czytając w sieci różne za i przeciw by w końcu dość impulsywnie skusić się. Mam wrażenie, że masa negatywnych opinii o iPhone pochodzi od ludzi, którzy tego telefonu w ręku nie mieli, a co dopiero mówić o dłuższym używaniu. Swoją drogą gdybym dorwał HTC w swoje ręce przed zakupem to nie wiem czy pisałbym o nim jako swoim poprzednim telefonie teraz.&lt;/p&gt;
&lt;h3&gt;Pierwsze wrażenie&lt;/h3&gt;
&lt;p&gt;Jak już człowiek coś kupi to liczy, że to co nabył będzie sprawować się bezproblemowo od samego początku. W wypadku iPhone wszystko przebiegło sprawnie (choć ten wymóg posiadania iTunes na komputerze może niektórych trochę drażnić) i po kilkunastu minutach telefon był gotów do boju (miałem przez parę minut stracha, że nieszczęśliwie trafiłem z chipsetem w laptopie &lt;sup&gt;[2]&lt;/sup&gt;). Jeśli chodzi o HTC to dwie &quot;przygody&quot; są warte odnotowania - po pierwsze kalibracja ekranu - do dziś coś mnie trafia jak mam ją przeprowadzić (na szczęście to rzadka &quot;przyjemność&quot;) - generalnie opiera się to na macaniu ekranu w nadziei, że kiedyś się uda. Druga sprawa - telefon się włączył, wszystko ładnie, pięknie - zaczynamy podróżować palcem po ekranie i w tym momencie po prostu czuć, że to nie to… coś jest nie tak - telefon zwyczajnie MULI. I rzeczywiście - firmware 1.37 (o ile dobrze pamiętam) był IMHO z lekka niedorobiony, interfejs Touch Flo 3D po prostu się wlókł - do płynności z filmów pokazowych brakowało mu dużo… za dużo… Oczywiście problem udało się jakoś rozwiązać - ściągnąłem jakiś magiczny software, zwiększyłem to i owo, odhaczyłem tamto i owamto - zaczęło działać znośnie choć ciągle to nie było to czego bym chciał, ale lepszych rozwiązań wtedy nie udało się znaleźć. Dopiero wraz z firmware 2.* telefon zaczął działać &quot;jako tako&quot;.&lt;/p&gt;
&lt;p&gt;Co do designu obu telefonów i urządzeń pobocznych nie będę się rozwodził - oba telefony prezentują wysoki poziom projektu i wykonania - chyba tylko ktoś o wyszukanym guście mógłby powiedzieć, że są brzydkie.&lt;/p&gt;
&lt;h3&gt;Drugie wrażenie - czyli początki użytkowania&lt;/h3&gt;
&lt;p&gt;Jest parę operacji, które wykonuję bardzo często w telefonie i jestem wniebowzięty jeżeli przebiega to tak sprawnie, że nie muszę prawie zwracać na to uwagi. W iPhone po kliknięciu przycisku zasilania włącza się blokada klawiszy, kliknięcie największego przycisku powoduje aktywowanie ekranu, włączenie alarmu wibracyjnego to kwestia przestawienia jednego przełącznika na obudowie telefonu, odłożenie telefonu od ucha powoduje aktywowanie się ekranu, który się wyłącza w momencie przyłożenia aparatu do ucha. W HTC żadne z tych udogodnień standardowo nie istniało. Oczywiście - zapewne większość z tych zachcianek można spełnić poprzez zmianę czegoś tam w ustawieniach lub instalację kolejnej dziwnej malutkiej aplikacji, która zrobi to za nas. Tylko pytam się - dlaczego nie było tak oczywistych funkcjonalności w standardzie ? Potem jako nowicjusz włóczy się człowiek po forach szukając rozwiązań w sprawach o których powinni pomyśleć producenci aparatu i oprogramowania!&lt;/p&gt;
&lt;p&gt;I jeszcze jedna wielka wada mojego HTC - nie dociekłem czy to kwestia jakichś ustawień czy po prostu on tak ma, ale w czasie rozmowy (tak - takie telefony do tego też czasem służą ;) dźwięk rozmówcy był zdecydowanie za cichy - do tego stopnia, że właściwie w bardziej tłocznym i gwarnym miejscu po prostu często nie dało się porozmawiać, bo nie było nic słychać.&lt;/p&gt;
&lt;p&gt;I jeden plus dla HTC - coś czego mi trochę brakuje na co dzień w iPhone - podświetlane kółeczko sygnalizujące nieodebrane połączenia/wiadomości - świetny pomysł, bo lubię wyjść w teren bez telefonu - dzięki niemu przy powrocie od razu widziałem czy ktoś czegoś ode mnie nie chciał bez ruszania telefonu.&lt;/p&gt;
&lt;h3&gt;System operacyjny - WM 6.1 vs. iPhone OS&lt;/h3&gt;
&lt;p&gt;No w tej kwestii to iPhone miażdży zupełnie HTC. WM 6.1 to totalna pomyłka dla telefonu z dotykowym wyświetlaczem - obsługiwanie systemu palcem poza Touch Flo 3D jest po prostu uciążliwe. Jakoś tą sztukę opanowałem po pewnym czasie - natomiast nie wyobrażam sobie używać rysika do podstawowych spraw typu pisanie SMS-ów czy obsługa systemu - nie po to kupowałem telefon z dotykowym wyświetlaczem by posuwać po nim rysikiem - w takiej sytuacji już lepiej sprawić sobie coś z klawiaturą QWERTY - zwyczajnie mniej upierdliwe i nie zgubi się ciągle wyciąganego i wkładanego rysika (na plus HTC dodam, że pomyśleli o zapasowym w zestawie). Rysik od zawsze akceptowałem tylko do odręcznych notatek ;) Kolejna sprawa to tragiczny wygląd samego systemu - wychodząc poza Touch Flo 3D ma się wrażenia cofnięcia o 3 epoki do ery Windows 98 - bo tak mniej więcej wygląda interfejs. W iPhone OS wszystko wygląda porządnie, wszelkie przyciski są wystarczająco duże by w nie trafić, a sam interfejs w większości aplikacji jest spójny i intuicyjny. Jeżeli chodzi o szybkość działania to co tu kryć - WM 6.1 chodził według mnie dość topornie - nawet odpalenie Opery chwilę trwało - w porównaniu do Safari z iPhone OS to tak jakby porównywać Firefoksa do Google Chrome - kto używa obu ten wie o czym mówię.&lt;/p&gt;
&lt;p&gt;Właściwie jest jedna wada iPhone OS, która niektórych może martwić - brak możliwości działania aplikacji z AppStore w tle (bo np. muzyki w tle da się posłuchać). Zamiast tego istnieje PUSH, który okresowo wykonuje magiczne operacje typu: sprawdzenie ile maili nam doszło na skrzynce pocztowej. Oficjalnie chodzi o kwestię użycia baterii, nieoficjalnie nie wnikałem jaki jest powód takiego ograniczenia. Tak naprawdę ta wada jest zauważalna tylko wtedy kiedy użytkownik ma ogromną potrzebę bycia online nawet gdy telefon leży sobie spokojnie w kieszeni (inaczej mówiąc musisz mieć wiecznie odpalony komunikator IM w tle - szczerze mówiąc innych zastosowań dla aplikacji na telefon działających w tle za bardzo nie widzę) - ja takiej potrzeby nigdy nie miałem i raczej mieć nie będę, zwłaszcza że na telefonie z racji gabarytów i tak wiele nie zdziałasz w sprawach zawodowych (to samo zrobisz via SMS, a jeszcze szybciej i lepiej poprzez rozmowę telefoniczną), a ukochana/ukochany z reguły są w stanie przeżyć chwile naszej nieobecności albo już mają wykupiony pakiet darmowych SMS-ów / rozmów na nasz numer. A dla tych, którzy naprawdę mają takie potrzeby pozostaje zapewne rozwiązanie a'la HTC - &quot;Jailbreak + jakaśMagicznaAplikacja&quot;, bo pewnie się jakoś da odpalić kilka aplikacji naraz. Ale tak między nami - trochę geekowato jak już nawet w kolejce po ogórki w osiedlowym spożywczaku masz potrzebę pogadania poprzez XMPP z kimś ;)&lt;/p&gt;
&lt;h3&gt;Trochę o hardware&lt;/h3&gt;
&lt;p&gt;Czułość wyświetlacza w iPhone jest nieporównywalnie lepsza od tej z HTC - jak dla mnie dwa światy, co widzę szczególnie teraz użytkując oba telefony naraz - w HTC muszę dość mocno naciskać ekran bo gesty z którymi się oswoiłem w iPhone nie powodują żadnej reakcji wyświetlacza HTC.&lt;/p&gt;
&lt;p&gt;Rozmiary wyświetlacza - te 0.7 cala w wymiarach wyświetlaczy robi ogromną różnicę. Można by narzekać, że rozdzielczość wyświetlacza w iPhone jest za mała, ale według mnie 640x480 w HTC to jest gruba przesada - w iPhone wcale nie odczułem bym potrzebował większej rozdzielczości - jest tak akurat :) Jest to doskonały przykład tego jak większe cyferki w specyfikacji wcale nie znaczą, że coś jest lepsze. Tak swoją drogą kiedyś odpaliłem jakąś grę w rozdzielczości jaką oferuje maksymalnie HTC - bez rysika nie podchodź! - a co do rysika to już się wypowiadałem ;)&lt;/p&gt;
&lt;p&gt;Multitouch - no cóż, kto bawił się jakąś ciekawszą aplikacją na iPhone (np. Google Earth) ten wie, że to cudo ;)&lt;/p&gt;
&lt;p&gt;Aparat fotograficzny - tu w zasadzie nie wiem czy w ogóle jest sens oceniać - jak dla mnie aparat w telefonie to coś co po prostu ma być po to by można było sfotografować &quot;na szybko&quot; coś istotnego. Oba telefony mają podobnej jakości osprzęt i nigdy nie miałem wysokich wymagań w tej kwestii. Tym którzy lecą na 10MPix w telefonie gratuluję znajomości praw fizyki ;) Jeżeli zaś chodzi o lampę - w swoim SE ją mam i kiedyś nawet robiłem z jej użyciem zdjęcia w nocy - szczerze mówiąc szału nie było i dużo więcej na zdjęciach widać nie było - mam wrażenie, że z tymi lampami podobnie jak z tymi megapikselami - fajnie wygląda to w specyfikacji telefonu, bo praktyczność takiego rozwiązania znajduje się dużo poniżej oczekiwań.&lt;/p&gt;
&lt;p&gt;Bateria - HTC wytrzymywał mi około 3 dni na standardowej baterii jak prawie nic z nim nie robiłem. Przy przeciętnym użytkowaniu bateria potrafiła paść po jednym dniu (i z tego co czytałem w sieci to raczej normalne). Pewnie da się znowu jakimiś szamańskimi metodami to zmienić, ale ja na takie zabawy zwyczajnie nie miałem czasu i oszczędzanie baterii skończyło się u mnie na wyłączeniu 3G w telefonie. iPhone natomiast wytrzymuje mi średnio 2 dni przy 6 godzinach użytkowania przy WŁĄCZONYM 3G (sam pomysł umieszczenia tego typu informacji w łatwo dostępnym miejscu jest świetny) - w HTC o takich osiągach mogłem co najwyżej pomarzyć (może większa bateria dałaby radę).&lt;/p&gt;
&lt;p&gt;Kamera do rozmów wideo - to jest kolejny gadżet z HTC, którego NIGDY nie użyłem i który fajnie wygląda tylko w specyfikacji telefonu. BTW czy ktoś w ogóle prowadził wideo-rozmowy w celach innych niż testowe ? Mam wrażenie, że ten wynalazek to coś pokroju WAP - niby super-ekstra-nowoczesne ale tak naprawdę do niczego nieprzydatne - krótko mówiąc : bezużyteczny bajer. Tak naprawdę nawet te MMS-y których brak obsługi niektórzy mocno wytykali w starszych iPhone - wydawały mi się przez wiele lat zbędne. Dopiero jakoś od okresu wakacji mi się przydały w wypadku jednej osoby, ale jeżeli w takim tempie to idzie to na pewno do czasu kiedy wideo-rozmowy będą mi potrzebne iPhone się w dodatkową kamerkę uzbroi :)&lt;/p&gt;
&lt;h3&gt;Inne aplikacje&lt;/h3&gt;
&lt;p&gt;App Store to miejsce, które po prostu wciąga - ogromna ilość aplikacji z czego duża część darmowa. Popularność iPhone sprawiła, że możemy liczyć na dostępność pozycji od naprawdę znanych i cenionych firm takich jak Electronic Arts czy Autodesk. Można narzekać, że co fajniejsze aplikacje/gry są płatne ale spójrzmy prawdzie w oczy - stać Cię na utrzymanie telefonu wynoszące w sumie kilka tysięcy PLN, a szkoda Ci wydać 3 euro na pełną wersję gry ? No wtedy coś tu nie gra na mój gust. Osobiście jeszcze nie udało mi się znaleźć czegoś co byłoby mi potrzebne i nie znajdowało się w App Store ;)&lt;/p&gt;
&lt;p&gt;Fajnie gdy można zainstalować aplikacje z innych źródeł, ale z drugiej strony - pobierając/kupując w App Store mamy prawie 100% pewność, że pobrane oprogramowanie jest wolne od złośliwego kodu i zostało przetestowane na naszej platformie - czyli krótko mówiąc - zadziała.&lt;/p&gt;
&lt;p&gt;A co do ciekawych gier/aplikacji - to temat na osobny wpis, który się kiedyś na pewno pojawi ;)&lt;/p&gt;
&lt;h3&gt;Programowanie&lt;/h3&gt;
&lt;p&gt;Pisanie aplikacji to jeden z nielicznych obszarów gdzie mój poczciwy HTC ma wciąż dużą przewagę nad iPhone - Visual Studio , SDK i można pisać pod Windows Mobile (np. w moim ulubionym C#).&lt;/p&gt;
&lt;p&gt;Z iPhone OS jest trochę gorzej - po pierwsze musisz mieć maca. Po drugie musisz znać dość nietypowy język jakim jest Objective-C - poza środowiskiem MacOS raczej niespotykany (są też jakieś rozwiązania by pisać dla iPhone w innych językach, ale nie zgłębiałem tego tematu jeszcze). I wreszcie po trzecie - aby móc przetestować swoją aplikację musisz wydać $99 na certyfikat, który umożliwi odpalenie aplikacji na telefonie - bez tego pozostaje testowanie w emulatorze. Oczywiście można emulować MacOS, a certyfikat zapewne ominie się przez Jailbreak, ale na mój gust przy takiej kombinacji dochodzi punkt czwarty - kupno koszulki &quot;jestem hardkorem&quot; (zwłaszcza gdy chcesz sobie wmówić, że emulowany MacOS wcale nie muli ;)&lt;/p&gt;
&lt;p&gt;Samo środowisko programistyczne z SDK jest porządne - XCode wraz z Interface Builder-em i emulatorem iPhone tworzą całkiem zgrabne trio (choć i tak bardziej lubię Visual Studio). Dla prawdziwych zapaleńców widziałem nawet jakiś Shader Builder&lt;sup&gt;[3]&lt;/sup&gt; do OpenGL.&lt;/p&gt;
&lt;p&gt;A swoją drogą co do OpenGL pod iPhone to wątek jest dość ciekawy i intrygujący (przynajmniej dla mnie), przy czym tworzenie aplikacji w OpenGL ES jest &quot;odrobinkę&quot; bardziej uciążliwe niż ma to miejsce w przypadku tradycyjnych platform - pierwsza rzecz, która rzuca się w oczy to brak instrukcji &lt;b&gt;glBegin&lt;/b&gt; i &lt;b&gt;glEnd&lt;/b&gt; - w ramach optymalizacji trzeba korzystać z tablic wierzchołków. Druga rzecz, która już mi się rzuciła w oczy - &lt;b&gt;glRotate&lt;/b&gt;, &lt;b&gt;glScale&lt;/b&gt;, &lt;b&gt;glTranslate&lt;/b&gt; może i istnieją w specyfikacji OpenGL ES, ale natychmiastowe pady emulatora dały mi do zrozumienia, że chyba jednak zamiast tych instrukcji należy stosować ręcznie macierze transformacji - także chyba będzie trzeba w końcu je sobie wydrukować i powiesić nad łóżkiem. Zresztą z tego co wyczytałem standardowe instrukcje transformacji są dość nieefektywne w iPhone… no dobra… koniec wywodu może pokuszę się kiedyś o wpis na temat OGL w iPhone jak zgłębię temat i Objective-C ;)&lt;/p&gt;
&lt;h3&gt;Pozostałe&lt;/h3&gt;
&lt;p&gt;Wpis się trochę rozrósł a i tak pewne kwestie prawdopodobnie pominąłem - gdyby kogoś interesowało coś konkretnego to proszę śmiało pytać :)&lt;/p&gt;
&lt;h3&gt;Podsumowanie&lt;/h3&gt;
&lt;p&gt;Nie ukrywam, że HTC Touch Diamond rozczarowuje przy iPhone - mam wrażenie, że jest nieprzemyślanym i niedopracowanym produktem - kiepski (zwłaszcza przy iPhone) ekran, system operacyjny niedostosowany do telefonów z dotykowym wyświetlaczem, wolne działanie standardowej konfiguracji czy brak wielu udogodnień zwiększających wygodę użytkowania to podstawowe bolączki tego telefonu. Posiada udogodnienia z których 99% użytkowników nigdy nie skorzysta (patrz np. kamerka do wideo-rozmów). Z kolei iPhone ma wszystko to czego potrzeba normalnemu użytkownikowi telefonu, a nawet trochę więcej - jest to telefon który w pełni zasługuje na miano multimedialnego. HTC jest dobry dla osób, które lubią dużo grzebać przy swoim telefonie (choć iPhone po Jailbreak prawdopodobnie pod względem możliwości modyfikacji mu nie ustępuje) i mają czas na to by przeszukiwać fora w poszukiwaniu odpowiedzi na swoje potrzeby. Przeciętnemu użytkownikowi iPhone sprawi zdecydowanie mniej problemów i więcej przyjemności z użytkowania.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;[1] niestety jest to przedział &quot;Chyba Cię #%#$^!&amp;amp;%&amp;amp;*%, że można wydać tyle na telefon ?!&quot;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;[2] &lt;a href=&quot;http://tech.wp.pl/kat,1009781,title,Windows-7-nie-widzi-iPhonea,wid,11662966,wiadomosc.html?ticaid=195ab&quot;&gt;http://tech.wp.pl/kat,1009781,title,Windows-7-nie-widzi-iPhonea,wid,11662966,wiadomosc.html?ticaid=195ab&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;[3] &lt;a href=&quot;http://developer.apple.com/graphicsimaging/opengl/shader_image.html&quot;&gt;http://developer.apple.com/graphicsimaging/opengl/shader_image.html&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
</description><pubDate>Mon, 28 Dec 2009 14:54:14 +0100</pubDate><guid>http://blog.dziudek.pl/2009/12/28/htc-vs-iphone/</guid><category>iPhone</category></item><item><title>iPhone ciągle łączy się z siecią ?</title><link>http://blog.dziudek.pl/2009/12/27/iphone-ciagle-laczy-sie-z-siecia/</link><description>&lt;p&gt;Tytuł wpisu może być odrobinę mylący, bo tak naprawdę opisywany problem nie tyczy się tylko iPhone, ale po prostu poszukując odpowiedzi na tego typu pytanie nie znalazłem satysfakcjonującej mnie odpowiedzi (Wujku Google - indeksuj) a z tego co widziałem sporo osób miało/ma/będzie mieć podobny problem.&lt;/p&gt;
&lt;p&gt;Otóż jakiś czas temu zauważyłem, że bateria w iPhone po prostu znika w oczach, mimo że telefon nie był prawie używany - naładowałem telefon przed snem, wstaję rano (dodam, że sypiam względnie mało ;) a bateria wskazuje &lt;strong&gt;~75%&lt;/strong&gt; przy paru minutach używania - coś jest nie tak. Po południu zauważyłem a właściwie usłyszałem w radio zakłócenia typowe dla telefonu, który pobiera jakieś dane/łączy się z siecią. Nie byłoby w tym nic nadzwyczajnego gdyby nie to, że trwało to non-stop. Zacząłem szukać w sieci - odpowiedzi kręciły się w obrębie motywów typu &lt;em&gt;&quot;przeprowadź restore systemu&quot;&lt;/em&gt;, &lt;em&gt;&quot;Jailbreak-&amp;gt;jakaśMagicznaAplikacja&quot;&lt;/em&gt;, &lt;em&gt;&quot;Wejdź na stronkę X to wyłączysz Edge/3G itd.&quot;&lt;/em&gt;. Wszystko fajnie ale nie miałem jakoś zamiaru rozstawać się z dostępem do sieci, który mam wliczony w abonament a włączanie i wyłączanie Internetu przez jakieś cudo po Jailbreak-u też mi się nie uśmiechało zwłaszcza, że po prostu ewidentnie coś się łączyło w tle z siecią (widać to było w iBOA w spisie transmisji danych). Restore systemu też nie pomógł.&lt;/p&gt;
&lt;p&gt;Co pomogło ? Otóż przeniosłem telefon po naładowaniu (padł po 16h przy ~30 minutach używania) dosłownie 3 metry w stronę okna na stoliczek. Wstaję rano - voila ! Bateria wskazywała &lt;strong&gt;97%&lt;/strong&gt; po całej nocy czuwania. Co ciekawe przeniosłem z tego stolika drugi telefon (HTC) na biurko (z obawy, że wstając rano do budzika z iPhone zabiję się o drukarkę i szkło z potłuczonego drukarką stolika) - słyszałem przed snem w radio, że też coś się łączy z siecią - telefon padł po 11h prawie nieużywany w tym czasie.&lt;/p&gt;
&lt;p&gt;Wniosek ? Prawdopodobnie sygnał z nadajnika był przez jakiś czas słabszy (po 3 dniach problem zniknął) i telefony namiętnie łączyły się z siecią jak to mówią - do oporu, co skutkowało dużym zużyciem baterii i nie wiedzieć czego w wypadku iPhone także transferu (dosłownie kilkanaście kB danych, ale gdy ktoś jest rozliczany za każde połączenie z transmisją danych to robi się z tego niebagatelna sumka). Ogólnie warto sprawdzić czy przypadkiem nasz najbliższy nadajnik nie ma gorszego dnia, zamiast kombinować z różnymi dziwnymi rozwiązaniami ;)&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;P.S.: Podziękowania dla mojego jeszcze nie wypartego przez streaming radia z Internetu radiobudzika za pomoc w detekcji problemu ;)&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;
</description><pubDate>Sun, 27 Dec 2009 09:45:06 +0100</pubDate><guid>http://blog.dziudek.pl/2009/12/27/iphone-ciagle-laczy-sie-z-siecia/</guid><category>iPhone</category></item><item><title>DOMContentLoaded</title><link>http://blog.dziudek.pl/2009/11/08/domcontentloaded/</link><description>&lt;p&gt;Dzisiejszy wpis dedykuję wszystkim wielbicielom zdarzenia &lt;b&gt;DOMContentLoaded&lt;/b&gt;. Niestety jak wszystko co dobre, wymaga ono ostrożności w stosowaniu.&lt;/p&gt;
&lt;p&gt;Dla zobrazowania sytuacji dwa przykłady.&lt;/p&gt;
&lt;p&gt;W MooTools 1.1.1 (niektórzy muszą wciąż na nim bazować - i nie jest to wcale małe grono) implementacja zdarzenia &lt;b&gt;domready&lt;/b&gt; sprawia, że w IE powstają czasami dziwne błędy wynikające z tego, że zdarzenie to występuje PRZED wczytaniem kompletnego drzewa dokumentu. Efektem jest z reguły na wpół załadowana strona. Żeby było jeszcze ciekawiej to problem ten występuje tylko w niektórych przypadkach - niestety nie udało mi się jeszcze wykryć kiedy dokładnie to się dzieje ze względu na złożoność stron, które posiadały ten problem. Jedno jest pewne - w MooTools 1.1.1 stosowanie zdarzenia &lt;b&gt;domready&lt;/b&gt; właściwie odpada na stronach gdzie użytkownik może swobodnie dodawać nowe moduły z treścią - w konkretnej konfiguracji nasz skrypt może pięknie działać w IE ale wystarczy, że użytkownik włączy dodatkowe moduły i wtedy mogą wystąpić poważne problemy - lepiej nie ryzykować zwłaszcza, że widok strony, która wczytała się do połowy wcale nie powoduje przywołania na myśl tego, że przyczyną może być źle działający skrypt.&lt;/p&gt;
&lt;p&gt;Drugi problem tyczy się także stron gdzie mogą się pojawić później dodatkowe elementy. Jako przykład przytoczę tu skryptowe wyrównywanie kolumn - pierwsza myśl przy tworzeniu takowego skryptu jest jasna - niech to wyrównywanie wykona się najszybciej jak to tylko jest możliwe. I wszystko zapewne będzie działać pięknie do momentu w którym na stronie nie pojawi się po jakimś czasie dodatkowy skrypt, który będzie modyfikował wysokość elementów w treści kolumny i oczywiście złośliwie korzystał ze zdarzenia &lt;b&gt;onLoad&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Reasumując ten krótki wpis - decyzja o korzystaniu ze zdarzenia &lt;b&gt;DOMContentLoaded&lt;/b&gt; powinna wynikać nie tylko z zalet tego rozwiązania, ale także z przeanalizowania przyszłych losów tworzonej strony - jeżeli wiemy, że strona jest tak zbudowana iż umożliwia użytkownikowi spore zmiany w zakresie układu witryny i dodawanie dodatkowych rozwiązań bez naszego udziału to rada jest krótka - lepiej zapomnieć o stosowaniu tego zdarzenia.&lt;/p&gt;
</description><pubDate>Sun, 08 Nov 2009 19:53:06 +0100</pubDate><guid>http://blog.dziudek.pl/2009/11/08/domcontentloaded/</guid><category>JavaScript</category><category>mootools</category><category>Techblog</category><category>Webmastering</category><category>mootools</category><category>javascript</category></item><item><title>piąty semestr</title><link>http://blog.dziudek.pl/2009/10/10/piaty-semestr/</link><description>&lt;p&gt;Dwa tygodnie uczelni minęły mi w ekspresowym tempie. Przeprowadziłem już małe rozpoznanie przedmiotów (sztuk 7 + wf + język obcy). Po małych rotacjach z fakultetami, (których pół roku temu w ogóle miało nie być, a potem w magiczny sposób się pojawiły) wybrałem cybernetykę zamiast zaawansowanych systemów baz danych - nie będę ukrywał z czysto praktycznych względów: po pierwsze - mam o 30h w semestrze mniej, po drugie - cybernetyka rysuje się na dość łatwe do zdobycia 4 punkty ECTS, po trzecie - nie strawiłbym kolejnego semestru tłumaczenia mi SQL, a od administracji SQL Server mam piękną książkę, która w razie potrzeby wyjaśni mi to co trzeba 100 razy lepiej niż prowadzący laborki, którzy musieli się nagle przerzucić z Oracle na platformę Microsoftu.&lt;/p&gt;
&lt;p&gt;Poza cybernetyką mam też potworka zwanego Historią sztuki i estetyki. Pierwszy wykład był o wszystkim tylko nie o tym na co wskazuje nazwa przedmiotu. Może to się zmieni, ale ogólnie ów przedmiot wygląda na (delikatnie mówiąc) zapychacz wymyślony przez jakiegoś nawiedzonego humanistę - szczerze mówiąc bardziej obcuję ze sztuką przeglądając swoje RSSy niż na wspomnianym wykładzie...&lt;/p&gt;
&lt;p&gt;Z typowo &quot;graficznych&quot; przedmiotów (wszak specjalizacja pt. Grafika Komputerowa i Multimedia zobowiązuje :P) mam przedmiot Podstawy kompozycji (z oceną jeszcze się wstrzymam) oraz modelowanie i animacja - niestety patrząc na przebieg zajęć mam obawy czy bym to ogarnął nie mając za sobą dłuższej praktyki w 3d std MAX (w moim rankingu zajęć na które chodzę bo wypada, zajmuje on niechlubne drugie miejsce). No i to tyle przedmiotów, które trzeba po prostu przetrwać (choć w wypadku modelowania i animacji, pewnie przetrwanie będzie wymagało paru nocek spędzonych z wizualizacją i animacją na zaliczenie).&lt;/p&gt;
&lt;p&gt;Z przedmiotów, które zapowiadają się konkretnie mam Inżynierię Oprogramowania - na labolatorium przypadła mi z kolegą zacna rola architekta systemu - krótko mówiąc murzyn grupy do pisania raportów i patrzenia czy system równo puchnie. Ale ogólnie sam przedmiot zapowiada się względnie ciekawie.&lt;/p&gt;
&lt;p&gt;Programowanie komunikacji człowiek-komputer to przedmiot na którym mają mnie nauczyć XML-a i wszystkich języków z jego otoczki. Laborki to raczej banał. Chyba, że zadania z XSLT będą wymagały jakiejś magicznej wiedzy matematycznej.&lt;/p&gt;
&lt;p&gt;No i na deser - programowanie aplikacji graficznych. Jedyny przedmiot w tym sem z którego wykład mnie nie usypia, a trzeba dodać, że zaczyna się on o 8:30. Laboratorium z tego przedmiotu jest względnie wymagające - na początek czeka nas pisanie parsera formatu *.3ds (byłoby łatwiej gdyby miał on oficjalną dokumentację, a nie masę opracowań bazujących na domysłach autorów :P), potem wizualizacja wybranego zjawiska fizycznego, a na koniec własny shader. Wszystko w OpenGL, którego nie spisałem na straty po tym jak widzę, że WebGL coraz wyraźniej pojawia się na horyzoncie.&lt;/p&gt;
&lt;p&gt;Sumarycznie wychodzą mi 24 godziny zajęć w tygodniu (w drugiej połowie semestru 22h), czyli nie jest źle ;)&lt;/p&gt;
</description><pubDate>Sat, 10 Oct 2009 10:54:14 +0200</pubDate><guid>http://blog.dziudek.pl/2009/10/10/piaty-semestr/</guid><category>Ogólne</category><category>Studia</category></item><item><title>Jestem oazą spokoju...</title><link>http://blog.dziudek.pl/2009/09/20/jestem-oaza-spokoju/</link><description>&lt;p&gt;&lt;a href=&quot;http://drlex.jogger.pl/2005/05/16/jestem-oaza-spokoju/&quot;&gt;To&lt;/a&gt; mój ulubiony tekst związany z pracą. Istnieją dwie sytuacje, które mi o nim przypominają - testowanie strony na IE i kontakt z niektórymi użytkownikami naszych produktów. Skupię się na tym drugim, bo przez ponad 2 lata zaobserwowałem sporo ciekawych zjawisk. Fakt, że po dwóch latach mało co już człowieka dziwi i wyprowadza z równowagi.&lt;/p&gt;
&lt;p&gt;Mógłbym podzielić użytkowników na bardzo wiele grup, ale skupmy się na moich &quot;ulubionych&quot;. Istnieje wysokie prawdopodobieństwo, że jeżeli ktoś udziela wsparcia dla produktów używanych przez szersze grono osób to trafi na podobnych osobników.&lt;/p&gt;
&lt;h3&gt;Cudowne &quot;uzdrowienia&quot;&lt;/h3&gt;
&lt;p&gt;Pierwsza grupa użytkowników to te osoby, które poza zaśmiecaniem mi skrzynki mailowej i ewentualnie archiwum komunikatorów mało mnie irytuje. Typowy przypadek wygląda następująco:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dostaję e-mail z opisem problemu, który pojawił się nagle,&lt;/li&gt;
&lt;li&gt;Po upływie czasu z przedziału 5 minut - 2 godziny dostaję maila, że problem udało się rozwiązać bez mojego udziału&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Podejrzewam, że większość tych przypadków stanowią ludzie, którzy reagują na widok białej strony z napisem &quot;Fatal Error&quot; lub &quot;Warning&quot; dość spontanicznym wysyłaniem maili do kogo popadnie.&lt;/p&gt;
&lt;p&gt;Ktoś kogo osobiście bardzo cenię w dziedzinie tworzenia stron WWW powiedział mi kiedyś, że warto po otrzymaniu jakiegoś pytania odczekać trochę czasu - mnóstwo problemów rozwiązuje się wtedy samych - i to naprawdę działa.&lt;/p&gt;
&lt;h3&gt;Wybiórcza ślepota&lt;/h3&gt;
&lt;p&gt;Tytułowa przypadłość dotyka sporą grupę użytkowników - możesz napisać na czerwono w bloku z czerwonym obramowaniem, że archiwum z plikami należy wypakować przed instalacją a i tak znajdzie się całe grono osób, które tego nie zrobią, a spory odsetek z nich napisze o razu do Ciebie maila, że im coś nie działa. To schorzenie odnosi się też poza tekstem pisanym na czerwono do pola wyszukiwarki na forum, ale o tym za chwilę.&lt;/p&gt;
&lt;h3&gt;Powielacze&lt;/h3&gt;
&lt;p&gt;Mając forum z odpowiedziami na różne problemy, można liczyć, że wątki będą rzadko powielane, a raz rozwiązane problemy posłużą jako wskazówka dla innych. Nic bardziej mylnego - niektórzy chyba uważają, że jak im osobiście nie odpowiesz to nie jest to rozwiązanie ich problemu (który był rozwiązany już 10-20 razy w przeszłości na forum).&lt;/p&gt;
&lt;h3&gt;Wtórni analfabeci&lt;/h3&gt;
&lt;p&gt;Do każdego produktu dołączamy zawsze plik PDF z opisem konfiguracji, użytkowania itd. Pomyślcie co można poczuć gdy widzi się maila z pytaniem na które odpowiedź znajduje się na pierwszych stronach instrukcji ? Nie dysponuję dokładnymi analizami, ale śmiem przypuszczać, że jakieś 60-80% użytkowników w ogóle nie czyta instrukcji, a w razie jakichkolwiek problemów od razu pisze maila. Ponieważ staram się krzewić ideę czytania instrukcji, najczęściej odpisuję krótkie &quot;Please read manual&quot;, które jest wskazówką do rozwiązania 90% problemów. Oczywiście zdarza się trafić głową w mur - parę razy miałem do czynienia z osobnikami, którzy mieli do mnie wielki żal o to, że każę im sprawdzić w instrukcji zamiast odpowiedzieć na pytanie - dalsza dyskusja to z reguły prawdziwy test cierpliwości.&lt;/p&gt;
&lt;h3&gt;Przeróbki&lt;/h3&gt;
&lt;p&gt;Jeżeli niektórych oburzają stawki typu 50PLN za skrypt, to co powiecie na ludzi myślących, że od ręki i za darmo naniosę im w skrypcie zmiany, które można by sklasyfikować jako przeróbka roweru na samochód ? Zaręczam - jest ich wielu.&lt;/p&gt;
&lt;h3&gt;Samo przestało działać&lt;/h3&gt;
&lt;p&gt;Są też na tym świecie ludzie wierzący w to, że uwierzę w magiczne samouszkodzenie się skryptu. Życie na szczęście nauczyło mnie, że w oprogramowaniu nic nie psuje się samo z siebie i albo coś musiało się zmienić w konfiguracji serwera, albo w samym skrypcie. Potem zamiast od razu znaleźć przyczynę problemu trzeba robić przesłuchanie by w końcu dowiedzieć się, że jednak parę godzin temu coś było zmieniane, jakby nie można było tego od razu powiedzieć.&lt;/p&gt;
&lt;h3&gt;Czepialscy&lt;/h3&gt;
&lt;p&gt;Niektórzy osobnicy sprawiają wrażenie, że wstali rano tylko po to by Ci dogadać i doczepić się czegokolwiek. Miałem już osobnika, który się prawie awanturował o to, że w komentarzu w kodzie CSS jest literówka - na pewno miała ona ogromny wpływ na wygląd strony. Na szczęście z reguły idzie łatwo wyczuć czy ktoś ma rzeczywiście problem czy szuka zaczepki. Ciekawą podgrupą czepialskich są ludzie, którzy myślą, że pisząc na forum o 2 w nocy dostaną w ciągu godziny odpowiedź. Oczywiście ja od dwóch lat w ogóle nie sypiam i tylko czekam w gotowości z otwartym laptopem aż ktoś napisze coś na forum (dodajmy do tego fakt, że ów osobnik może pisać z USA jak również z Chin czy innej Indonezji).&lt;/p&gt;
&lt;h3&gt;Totalnie bezczelni&lt;/h3&gt;
&lt;p&gt;Ostatnia grupa, którą chcę opisać to osobnicy, którzy dopadli w swoje łapki nasze płatne produkty w sposób nielegalny. I pół biedy jak je po prostu mają - choć to też drażni, ale nie jesteśmy tak naiwni by wierzyć, że całkowicie wytępimy piractwo naszych produktów. Tak naprawdę totalna irytacja (i tu nawet po dwóch latach użerania się z różnymi dziwnymi ludźmi nie nauczyłem się patrzeć na to z dystansem) zaczyna się wtedy gdy taki osobnik zaczyna pisać na ogólnodostępnym forum z pytaniami odnośnie swojego nielegalnego produktu (tu już ciśnienie rośnie) i zaczyna się przeobrażać w osobnika z grupy czepialskich - tak w tym momencie każdego normalnego człowieka coś trafia. Osobiście mam troszkę inną nazwę na takie osoby, ale wolałbym się tu jednak powstrzymać od wulgaryzmów. Stopień bezczelności jest mniej więcej taki jakby złodziej samochodów zadzwonił do okradzionego z pretensjami, że tapicerka nie jest w jego ulubionym kolorze.&lt;/p&gt;
&lt;h3&gt;Zła wiadomość&lt;/h3&gt;
&lt;p&gt;Wspomnianych wyżej zachowań raczej nie da się raczej całkowicie wytępić dlatego jeżeli już je obserwujemy to czym prędzej należy nauczyć się podchodzić do nich z dystansem. Osobiście gdybym spotkał się pierwszy raz z tym z czym spotykam się obecnie codziennie to pewnie bym zrezygnował z takiego zajęcia po tygodniu. Miałem to szczęście, że poszczególne zachowania pojawiały się w pewnej przestrzeni czasu w miarę popularyzacji naszych produktów i co za tym idzie - powoli oswoiłem się z tym jacy ludzie potrafią być i co potrafią wymyślić. A wierzcie mi lub nie - ludzie potrafią dać czasem w kość mając złudzenie anonimowości w sieci.&lt;/p&gt;
</description><pubDate>Sun, 20 Sep 2009 16:13:18 +0200</pubDate><guid>http://blog.dziudek.pl/2009/09/20/jestem-oaza-spokoju/</guid><category>joomla</category><category>Ogólne</category><category>Webmastering</category></item><item><title>Przeglądarki...</title><link>http://blog.dziudek.pl/2009/09/12/przegladarki/</link><description>&lt;p&gt;Zaokrąglone rogi będą motywem przewodnim tego wpisu, bo idealnie wiążą się z tematem, który chciałbym poruszyć. Sądzę, że przewija się on w głowie niejednej osoby, która miała okazję składać strony WWW.&lt;/p&gt;
&lt;p&gt;Otóż zawsze gdy dostaję do poskładania layout skacze mi ciśnienie gdy widzę w nim zaokrąglone rogi. Nie... Nie dlatego, że ten motyw na stronach WWW już wystarczająco mi się opatrzył. Po prostu zaokrąglone rogi to esencja pewnego problemu. Osoba dająca nam layout do poskładania oczywiście chce by był on jak to mówią - &quot;pixel perfect&quot; pod każdą przeglądarką (czyli pod tymi najpopularniejszymi). To oznacza pewne niedogodności. Weźmy na warsztat wspomniane zaokrąglone rogi - wszystkie normalne przeglądarki dorobiły się już ich obsługi za pomocą CSS. Problem polega na tym, że istnieje znana chyba wszystkim grupa &quot;nienormalnych&quot; przeglądarek, które tego udogodnienia za pomocą CSS nie obsługują. Pech chciał, że w skali globalnej te &quot;nienormalne&quot; przeglądarki mają około połowy udziałów w skali globalnej (mniejsza o to czy jest to 40% czy 60% - takiej grupy użytkowników nie można pominąć).&lt;/p&gt;
&lt;p&gt;I teraz specjalnie dla grupy osób używającej misiów do przeglądania stron WWW, osoba składająca stronę musi celem uzyskania zaokrąglonych rogów zamiast jednej linijki w kodzie CSS, tworzyć różne dziwne struktury - tym dziwniejsze im bardziej elastyczny ma być blok z zaokrąglonymi rogami). Te struktury to z reguły masa div-ów, które zawierają się w sobie nawzajem. I nie wiem jak Wy, ale mi bardzo często w czasie tworzenia takiej zacnej struktury div-ów po głowie chodzi jedno pytanie:&lt;/p&gt;
&lt;h3&gt;Po jaką cholerę ?&lt;/h3&gt;
&lt;p&gt;Oczywiście musicie zdać sobie sprawę z tego, że raczej nie uda się Wam tego wytłumaczyć waszemu grafikowi/klientowi.&lt;/p&gt;
&lt;p&gt;Warto jednak zastanowić się kto tak naprawdę używa IE ? Czy używa go ktoś kto ma jakieś pojęcie o tworzeniu stron WWW (nie wliczamy tu webmasterów, którzy na IE testują) ? Mogę się założyć, że przeciętny Kazio, będący typowym użytkownikiem IE, biorący pole input domyślnej wyszukiwarki za pasek adresu ma głęboko w poważaniu czy na stronie którą właśnie składamy będą zaokrąglone rogi czy nie. On po prostu jeżeli już w przyszłości na naszą stronę trafi, to nie będzie prowadził rozważań w stylu &quot;czy kolor linków został odpowiednio dobrany ?&quot; (no chyba, że grafik naprawdę schrzanił w tej kwestii dobór kolorów - ale tu działa taka magiczna zasada &quot;na sędziego meczu&quot; - możesz świetnie sędziować mecz piłkarski i nikt na Ciebie nie zwróci uwagi, ale spróbuj podyktować niesłuszny rzut karny i potem przez trzy tygodnie będziesz &quot;gwiazdą&quot; numer jeden w krajowej/lokalnej sieci). Przeciętny Kazio wejdzie na stronę, znajdzie co potrzebuje i sobie pójdzie.&lt;/p&gt;
&lt;p&gt;Czy warto zatem dla takich osób męczyć się, dokładać dodatkowe dziwne struktury w kodzie strony i tym samym zwiększać czas jej ładowania (no bo zaokrąglone rogi wymagają nie tylko więcej kodu (X)HTML, CSS, ale też dodatkowych grafik) ? Moja odpowiedź - nie. I moim małym marzeniem jest by ludzie, którzy potrzebują stron WWW w końcu zrozumieli, że w sieci podstawą jest informacja podana w czytelny sposób (o łatwości jej znalezienia w strukturze strony nie wspomnę), a detale typu zaokrąglone rogi nie są na tyle istotne (no może poza jakimiś ekstremalnymi przypadkami) by poświęcać na nie dodatkowy transfer danych i zapytania do serwera po dodatkowe grafiki.&lt;/p&gt;
&lt;p&gt;Po prostu ludzie, którzy patrzą bardziej szczegółowo na jakość wykonania stron nie używają IE (na pewno trafią się jakieś dziwne jednostkowe przypadki, ale z rachunku prawdopodobieństwa wynika, że szansa iż taki osobnik trafi na naszą stronę jest bardzo mała) - oni używają normalnych przeglądarek, które wspierają nowoczesne rozwiązania i takim osobom można serwować dopieszczone wizualnie strony z przejrzystym kodem.&lt;/p&gt;
&lt;p&gt;Ktoś powie, że to pójście na łatwiznę, ale może jest to po prostu pójście po rozum do głowy ? Po co mamy z uporem maniaka pokazywać użytkownikom IE, że w nim też można uzyskać ładne wizualnie strony, skoro i tak 99.999% z nich nie zwróci na to w ogóle uwagi?&lt;/p&gt;
</description><pubDate>Sat, 12 Sep 2009 20:26:24 +0200</pubDate><guid>http://blog.dziudek.pl/2009/09/12/przegladarki/</guid><category>Webmastering</category></item><item><title>joomla.org nas chyba nie lubi</title><link>http://blog.dziudek.pl/2009/09/08/joomla-org-nas-chyba-nie-lubi/</link><description>&lt;p&gt;Niedawno szef dostał maila z serwisu extensions.joomla.org w którym mamy umieszczone nasze moduły. W skrócie: napisano w nim, że niedawno ktoś oddał 30 głosów w bardzo krótkim czasie na nasze produkty. Wszystkie głosy pochodziły z różnych kont i tego samego adresu IP. Zagrożono, że jeżeli sytuacja się powtórzy to nasze produkty zostaną usunięte z katalogu.&lt;/p&gt;
&lt;p&gt;Nie ukrywajmy - od razu można było wyczuć, że ktoś nam podkłada &quot;świnię&quot;. Bo jak można w tak naiwny i bezczelny sposób &quot;promować&quot; swoje produkty poprzez głosowania licząc, że nikt z administracji tego nie zauważy ?&lt;/p&gt;
&lt;p&gt;Oczywiście wysłaliśmy mail z wieloma pytaniami i wyjaśnieniami. W odpowiedzi dostaliśmy e-mail napisany na &quot;odwal się&quot; z informacją, że nasze produkty zostały zbanowane (najpierw ostrzegają, że jeżeli sytuacja się powtórzy to nas zbanują, a potem banują od razu - ciekawe...). Dodatkowo napisano by &quot;przypomnieć się&quot; ze zdjęciem bana w danym dniu. Albo ich system banowania jest w jakiejś dziwniej fazie beta albo istnieją jakieś inne magiczne powody dla których ban nie zostanie zdjęty automatycznie - stawiam na wiarę w to, że po prostu zapomnimy się upomnieć o zdjęcie bana. Po tym mailu z panem, który nas tak pięknie &quot;obsłużył&quot; skończyliśmy dyskusję bo było widać, że nie potrafi dopuścić do siebie myśli, że mamy wystarczająco dużo inteligencji by takich akcji nie przeprowadzać na ich stronie.&lt;/p&gt;
&lt;p&gt;Posłaliśmy maila z prośbą o wyjaśnienie tej sprawy do innego administratora i liczymy, że obiektywnie spojrzy na tą sprawę - osobnik, który się nią zajmował chyba o czymś takim jak obiektywność zapomniał (choć jak dla mnie nie tylko o obiektywności zapomniał).&lt;/p&gt;
&lt;p&gt;Jeżeli nasze produkty będą dalej banowane w katalogu to wniosek jest taki, że prawdopodobnie wystarczy założyć kilka/kilkanaście kont, głosować na produkty konkurencji z jednego IP i liczyć na to, że moderatorzy podobnie jak w naszym wypadku orzekną winę autorów danych produktów, usuwając je z katalogu. Słowa &quot;liczyć na to&quot; są tu jak najbardziej na miejscu, bo od dłuższego czasu mam dziwne wrażenie, że niektórzy mają na stronach joomla.org łatwiej niż inni.&lt;/p&gt;
&lt;p&gt;Względnie niedawno powstała strona resources.joomla.org docelowo mająca gromadzić wszelkie witryny związane z Joomla!. Dziwnym trafem nie zaakceptowano naszego zgłoszenia jako klubu oferującego szablony dla Joomla!. Zresztą nie ma w nim też takiego klubu jak Joomlart - powiedzmy sobie szczerze - to ogromny brak, bo to chyba największy gracz na tym rynku (&lt;strong&gt;ciekawostka:&lt;/strong&gt; Joomla! domyślnie po instalacji ma do wyboru jeden z ich darmowych szablonów - JA Purity). A co ciekawe w katalogu można znaleźć takie kluby oferujące szablony jak &lt;b&gt;www.pixelthemestudio.ca&lt;/b&gt; które żeby było śmieszniej - na stronie głównej korzystają ze zmodyfikowanego na własne potrzeby... naszego szablonu... Nie ukrywam, że w takiej sytuacji nie wiem czy się śmiać, czy płakać widząc taki &quot;katalog&quot;.&lt;/p&gt;
&lt;p&gt;Być może wadą naszych modułów i komponentów dla Joomla! która sprawiła, że wypadły z katalogu na extensions.joomla.org jest to, że są one bezpłatne i stanowią dla sporej grupy osób dobrą alternatywę w stosunku do płatnych modułów i komponentów innych firm. Oczywiście pozostanie to tylko w sferze naszych firmowych domysłów. Parę miesięcy temu zawiedliśmy się na obiektywności Smashing Magazine, teraz serwisy związane z joomla.org zaczynają zachowywać się podobnie.&lt;/p&gt;
&lt;p&gt;A ucierpią na tym tylko użytkownicy Joomla! - będą mieli wybór ograniczony do pewnej grupy produktów, które włodarze serwisów pochodnych joomla.org uznają za godne prezentowania w ich katalogach.&lt;/p&gt;
</description><pubDate>Tue, 08 Sep 2009 15:56:24 +0200</pubDate><guid>http://blog.dziudek.pl/2009/09/08/joomla-org-nas-chyba-nie-lubi/</guid><category>joomla</category><category>Ogólne</category></item><item><title>Jeszcze raz... :P</title><link>http://blog.dziudek.pl/2009/09/07/jeszcze-raz-p/</link><description>&lt;p&gt;Mógłbym Wam podać 50 rzeczy/wydarzeń/osób, które sprawiły, że rozstałem się ze swoim Joggerem na dłuższy okres czasu, ale po pierwsze - kto by to czytał ? Po drugie - czas, który poświęciłbym na pisanie tej zacnej listy, można spożytkować na inny wpis ;)&lt;/p&gt;
&lt;p&gt;Jedyne dwa istotne fakty:&lt;/p&gt;
&lt;p&gt;* Pewne jest, że wystąpi zjawisko pisania na tematy odbiegające (często dość mocno) od informatyki - bo prowadzenie dwóch blogów (technicznego i tego 'luźnego') odpadło z listy moich koncepcji.&lt;/p&gt;
&lt;p&gt;* Blip zaspokajał moje potrzeby przez dość długi czas, ale w pewnym momencie człowiek dochodzi do wniosku, że 160 znaków to za mało a same blipnięcia są dość... ulotne ;)&lt;/p&gt;
</description><pubDate>Mon, 07 Sep 2009 15:46:03 +0200</pubDate><guid>http://blog.dziudek.pl/2009/09/07/jeszcze-raz-p/</guid><category>Jogger</category><category>Ogólne</category></item><item><title>Żyję...</title><link>http://blog.dziudek.pl/2009/05/17/zyje/</link><description>&lt;p&gt;... i mam się w miarę dobrze. Gdyby ktoś się pytał czemu tak cicho: użeram się z dwoma dość czasochłonnymi projektami - &lt;a href=&quot;http://static3.blip.pl/user_generated/update_pictures/299761.jpg?1242482358&quot;&gt;to będzie moja koparka w OpenGL&lt;/a&gt;, a &lt;a href=&quot;http://static3.blip.pl/user_generated/update_pictures/301562.jpg?1242589110&quot;&gt;to będzie konsolowa wersja szachów japońskich&lt;/a&gt;, które jeszcze potem mają mieć GUI i parę innych drobiazgów. Także póki co się nie nudzę zwłaszcza, że w pracy też nie ma przebacz i trzeba robić to i owo ;)&lt;/p&gt;
&lt;p&gt;Ale parę ciekawych projektów MooToolso-pochodnych zalega w notatkach i czeka na realizację i upublicznienie ;) Pewnie po sesji ;)&lt;/p&gt;
</description><pubDate>Sun, 17 May 2009 21:54:07 +0200</pubDate><guid>http://blog.dziudek.pl/2009/05/17/zyje/</guid><category>Ogólne</category></item><item><title>Cytowanie prywatnych wiadomości na blipie</title><link>http://blog.dziudek.pl/2009/04/09/cytowanie-prywatnych-wiadomosci-na-blipie/</link><description>&lt;p&gt;Banalny &lt;a href=&quot;http://userscripts.org/scripts/show/46073&quot;&gt;userJS&lt;/a&gt; mojego autorstwa, który ma za zadanie odblokować cytowanie prywatnych wiadomości na blip.pl&lt;/p&gt;
</description><pubDate>Thu, 09 Apr 2009 13:00:14 +0200</pubDate><guid>http://blog.dziudek.pl/2009/04/09/cytowanie-prywatnych-wiadomosci-na-blipie/</guid><category>JavaScript</category><category>UserJS</category><category>Webmastering</category><category>javascript</category><category>blip</category></item><item><title>Powracamy...</title><link>http://blog.dziudek.pl/2009/04/09/powracamy/</link><description>&lt;p&gt;Wraz z trzecim semestrem na uczelni, po tym jak zafundowałem sobie zdecydowanie za dużo &quot;atrakcji&quot;, musiałem po cichu zawiesić prowadzenie tego bloga.&lt;/p&gt;
&lt;p&gt;Teraz, kiedy na uczelni wieje nudą, a ja mam zdecydowanie więcej wolnego czasu, wróciła mi ochota na pisanie. Może nie będę pisywał tak często jak dawniej, ale na pewno co jakiś czas pojawi się jakiś wpis związany z tematem tworzenia stron, a być może także coś związanego z Javą i OpenGL, które ostatnio namiętnie poznaję ;)&lt;/p&gt;
&lt;p&gt;Co tu dużo pisać - brakowało mi trochę jogger-a ;)&lt;/p&gt;
</description><pubDate>Thu, 09 Apr 2009 12:55:54 +0200</pubDate><guid>http://blog.dziudek.pl/2009/04/09/powracamy/</guid><category>Jogger</category><category>Ogólne</category></item><item><title>MooTools 1.2 - elementy strony cz. 3</title><link>http://blog.dziudek.pl/2008/09/28/mootools-1-2-elementy-strony-cz-3/</link><description>&lt;p&gt;W poprzednich częściach kursu nauczyliśmy się poruszać po drzewie dokumentu, tworzyć nowe elementy strony oraz zmieniać ich cechy, odczytywać je oraz przechowywać dodatkowe informacje w elementach. Przyszła pora poznać kilka metod dokonujących znaczących zmian w strukturze dokumentu - dwie z nich poznaliśmy wcześniej - &lt;b&gt;adopt&lt;/b&gt; i &lt;b&gt;clone&lt;/b&gt;, teraz nauczymy się kilku nowych.&lt;/p&gt;
&lt;h3&gt;Czy jesteś paragrafem ?&lt;/h3&gt;
&lt;p&gt;Wiemy, że typ elementu można sprawdzić za pomocą zapisu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.get('tag');{/geshi}&lt;/p&gt;
&lt;p&gt;Gdybyśmy jednak potrzebowali sprawdzić czy dany element jest określonego typu (przykładowo paragrafem) to zamiast pisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}if(element.get('tag') == 'p'){ // kod wykonywany po spełnieniu warunku }{/geshi}&lt;/p&gt;
&lt;p&gt;Możemy skorzystać z metody &lt;b&gt;match&lt;/b&gt;, która przyjmuje jako argument typ elementu i zwraca wartość &lt;b&gt;true&lt;/b&gt;, jeżeli dany element jest właśnie takiego typu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}if(element.match('p')){ // kod wykonywany po spełnieniu warunku }{/geshi}&lt;/p&gt;
&lt;p&gt;Przy okazji zapis warunku jest trochę krótszy.&lt;/p&gt;
&lt;h3&gt;Zmiany zawartości elementu&lt;/h3&gt;
&lt;p&gt;Wcześniej poznaliśmy też właściwości &lt;b&gt;text&lt;/b&gt; i &lt;b&gt;html&lt;/b&gt;, które pozwalały manipulować zawartością elementu. Aby wyczyścić element z wszelkich elementów i teksów należało zapisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.set('html','');{/geshi}&lt;/p&gt;
&lt;p&gt;Ale warto wiedzieć, że można to zapisać krócej za pomocą metody &lt;b&gt;empty&lt;/b&gt;, która robi to samo co poprzedni zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.empty();{/geshi}&lt;/p&gt;
&lt;p&gt;Możemy też dodawać do elementu tekst (i wokół niego) nie tylko za pomocą zapisu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.set('text', element.get('text')+'Nowy tekst');{/geshi}&lt;/p&gt;
&lt;p&gt;ale także za pomocą o wiele prostszego zapisu z użyciem metody &lt;b&gt;appendText&lt;/b&gt; o następującej składni:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.appendText('tekstDoDodania', 'pozycja');{/geshi}&lt;/p&gt;
&lt;p&gt;Parametr pozycja jest opcjonalny i przyjmuje jedną z czterech wartości: &lt;b&gt;top&lt;/b&gt;, &lt;b&gt;bottom&lt;/b&gt;, &lt;b&gt;before&lt;/b&gt;, &lt;b&gt;after&lt;/b&gt;. Wartość &lt;b&gt;bottom&lt;/b&gt; jest wartością domyślną.&lt;/p&gt;
&lt;p&gt;Najlepiej umiejscowienie tekstu po użyciu tych parametrów zademonstruje poniższy schematyczny kod:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}// BEFORE&lt;/p&gt;
&lt;div id=&quot;test&quot;&gt;// TOP
&lt;p&gt;Jakiś tekst&lt;/p&gt;
// BOTTOM&lt;/div&gt;
&lt;p&gt;// AFTER{/geshi}&lt;/p&gt;
&lt;p&gt;Po wywołaniu metody &lt;b&gt;appendText&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('test').appendText('Testowy tekst', pozycja);{/geshi}&lt;/p&gt;
&lt;p&gt;Ze zmienną pozycja mającą jedną ze wspomnianych wcześniej wartości tekst zostanie dodany w miejsce odpowiedniego komentarza.&lt;/p&gt;
&lt;h3&gt;Z elementami jest podobnie&lt;/h3&gt;
&lt;p&gt;Metoda &lt;b&gt;inject&lt;/b&gt; działa podobnie jak metoda &lt;b&gt;appendText&lt;/b&gt; z tą różnicą, że operuje na całych elementach. Druga różnica jest taka, że pierwszym argumentem tej metody jest punkt odniesienia dla pozycji, zatem zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element1.inject(element2, 'top');{/geshi}&lt;/p&gt;
&lt;p&gt;Spowoduje umieszczenie &lt;b&gt;element1&lt;/b&gt; na samym początku &lt;b&gt;element2&lt;/b&gt;. Na bazie tej metody i kilku wcześniej poznanych można zbudować całkiem szybko listę sortowalnych elementów.&lt;/p&gt;
&lt;p&gt;Przyjmijmy, że mamy listę nieuporządkowaną, która zawiera kilka pozycji z różnymi tekstami. Każda z tych pozycji jest wyposażona w przyciski &lt;i&gt;'przesuń w górę'&lt;/i&gt; i &lt;i&gt;'przesuń w dół'&lt;/i&gt; - oczywiście krańcowe elementy są pozbawione jednego przycisku (jest on ukrywany w sposób dynamiczny). Niech nasza lista posiada atrybut &lt;b&gt;id&lt;/b&gt; o wartości &quot;&lt;b&gt;dynamicList&lt;/b&gt;&quot;.&lt;/p&gt;
&lt;p&gt;Każda pozycja listy będzie miała następującą budowę:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tekst &lt;img src=&quot;up.png&quot; alt=&quot;Przesuń w górę&quot;&gt; &lt;img src=&quot;down.png&quot; alt=&quot;Przesuń w dół&quot;&gt;&lt;/li&gt;
&lt;li style=&quot;list-style: none&quot;&gt;{/geshi}&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do przemieszczania elementów wystarczy poniższy kod:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ $('dynamicList').getChildren().each(function(el){ el.getFirst('img').addEvent(&quot;click&quot;, function(){ el.inject(el.getPrevious(), 'before'); }); el.getLast('img').addEvent(&quot;click&quot;, function(){ el.inject(el.getNext(), 'after'); }); }); });{/geshi}&lt;/p&gt;
&lt;p&gt;Dla każdego elementu listy dokonujemy selekcji obu przycisków i dodajemy do nich zdarzenia zawierające metody &lt;b&gt;inject&lt;/b&gt;. Dla przycisku &lt;i&gt;&quot;Przesuń w górę&quot;&lt;/i&gt; wykonujemy kod dokonujący wstawienia danego elementu przed poprzednim elementem, w wypadku drugiego przycisku wstawiamy element po następującym po nim elemencie.&lt;/p&gt;
&lt;p&gt;Małą wada jest fakt, że krańcowe elementy nie mają ukrytych przycisków. Oczywiście można by ukrywać przycisk przy kliknięciu elementu w przesuwanych elementach i pokazywać potrzebne przyciski, które były ukryte, ale o wiele łatwiej jest stworzyć funkcję, która ukrywa pierwszy i ostatni przycisk w obrębie całej listy:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}function hideButtons(){ $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }{/geshi}&lt;/p&gt;
&lt;p&gt;Należy jeszcze uwzględnić fakt, że pewne przyciski trzeba ponownie pokazać użytkownikowi - zamiast pokazywać profilaktycznie wszystkie przyciski wystarczy dodać naszej funkcji jeden argument - element w którym należy ponownie pokazać przyciski:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}function hideButtons(el1, el2){ if($defined(el1)){ el1.getElements('img').setProperty('style','visibility:visible'); el2.getElements('img').setProperty('style','visibility:visible'); } $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }{/geshi}&lt;/p&gt;
&lt;p&gt;Warunek w pierwszej linijce funkcji jest potrzebny ponieważ musimy pamiętać, że trzeba dodatkowo ukryć przyciski przy inicjalizacji skryptu. Ostatecznie kod skryptu w całości wygląda następująco:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ $('dynamicList').getChildren().each(function(el){ el.getFirst('img').addEvent(&quot;click&quot;, function(){ el.inject(el.getPrevious(), 'before'); hideButtons(el.getNext(), el); }); el.getLast('img').addEvent(&quot;click&quot;, function(){ el.inject(el.getNext(), 'after'); hideButtons(el.getPrevious(), el); }); }); hideButtons(); }); function hideButtons(el1, el2){ if($defined(el1)){ el1.getElements('img').setProperty('style','visibility:visible'); el2.getElements('img').setProperty('style','visibility:visible'); } $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }{/geshi}&lt;/p&gt;
&lt;p&gt;Cały skrypt w akcji:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dziudek.dreamhosters.com/mootools12/examples/9/mootools9.html&quot;&gt;PRZYKŁAD 1&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Usuwanie elementów&lt;/h3&gt;
&lt;p&gt;W jednej z poprzednich części kursu poznaliśmy metodę &lt;b&gt;dispose&lt;/b&gt;, która pozwalała usunąć element z drzewa dokumentu. Istnieją jeszcze dwie inne metody, które pozwalają usuwać elementy - &lt;b&gt;destroy&lt;/b&gt; i &lt;b&gt;replaces&lt;/b&gt;. Metoda &lt;b&gt;destroy&lt;/b&gt; różni się od metody &lt;b&gt;dispose&lt;/b&gt; tym, że nie zwraca niczego, natomiast metoda &lt;b&gt;dispose&lt;/b&gt; zwracała nam usuwany z drzewa dokumentu element, który mogliśmy ponownie wstawić do dokumentu, na przykład za pomocą metody &lt;b&gt;inject&lt;/b&gt;. Z kolei metoda &lt;b&gt;replaces&lt;/b&gt; usuwa dany element i zastępuje go innym :&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}nowyElement.replaces(staryElement);{/geshi}&lt;/p&gt;
&lt;p&gt;Przy czym usuwanie w tej metodzie nie działa na zasadzie metody &lt;b&gt;destroy&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}staryElement.destroy();{/geshi}&lt;/p&gt;
&lt;p&gt;Ale na zasadzie metody &lt;b&gt;dispose&lt;/b&gt; - zatem zastępowany element możemy ponownie wstawić do dokumentu.&lt;/p&gt;
&lt;p&gt;Wzbogacimy naszą listę o możliwość usuwania elementów - dodamy do struktury pozycji listy dodatkowy przycisk:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tekst &lt;img src=&quot;up.png&quot; alt=&quot;Przesuń w górę&quot;&gt; &lt;img src=&quot;delete.png&quot; alt=&quot;Usuń ten element&quot;&gt; &lt;img src=&quot;down.png&quot; alt=&quot;Przesuń w dół&quot;&gt;&lt;/li&gt;
&lt;li style=&quot;list-style: none&quot;&gt;{/geshi}&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do jego obsługi wystarczy dodać poniższy kod w pętli dodającej zdarzenia do przycisków:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}el.getChildren('img')[1].addEvent(&quot;click&quot;, function(){ el.destroy(); hideButtons(); });{/geshi}&lt;/p&gt;
&lt;p&gt;Zatem cały kod prezentuje się teraz następująco:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ $('dynamicList').getChildren().each(function(el){ el.getFirst('img').addEvent(&quot;click&quot;, function(){ el.inject(el.getPrevious(), 'before'); hideButtons(el.getNext(), el); }); el.getLast('img').addEvent(&quot;click&quot;, function(){ el.inject(el.getNext(), 'after'); hideButtons(el.getPrevious(), el); }); el.getChildren('img')[1].addEvent(&quot;click&quot;, function(){ el.destroy(); hideButtons(); }); }); hideButtons(); }); function hideButtons(el1, el2){ if($defined(el1)){ el1.getElements('img').setProperty('style','visibility:visible'); el2.getElements('img').setProperty('style','visibility:visible'); } $('dynamicList').getFirst().getFirst('img').setProperty('style','visibility:hidden'); $('dynamicList').getLast().getLast('img').setProperty('style','visibility:hidden'); }{/geshi}&lt;/p&gt;
&lt;p&gt;Przykład po zmianach w akcji:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dziudek.dreamhosters.com/mootools12/examples/10/mootools10.html&quot;&gt;PRZYKŁAD 2&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Otaczanie elementów&lt;/h3&gt;
&lt;p&gt;Na koniec opiszę dwie metody - &lt;b&gt;grab&lt;/b&gt; i &lt;b&gt;wraps&lt;/b&gt;. Metoda &lt;b&gt;grab&lt;/b&gt; to odpowiednik metody &lt;b&gt;adopt&lt;/b&gt;, który akceptuje tylko jeden element. Opcjonalnie możemy określić pozycję dodawanego elementu - &lt;b&gt;top&lt;/b&gt; lub &lt;b&gt;bottom&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}rodzic.grab(potomek);{/geshi}&lt;/p&gt;
&lt;p&gt;W poniższym wypadku element potomny zostanie umieszczony na samym początku elementu-rodzica:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}rodzic.grab(potomek, 'top');{/geshi}&lt;/p&gt;
&lt;p&gt;W tym wypadku element potomny zostanie umieszczony jako ostatni element potomny elementu-rodzica:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}rodzic.grab(potomek, 'bottom');{/geshi}&lt;/p&gt;
&lt;p&gt;Różnica pomiędzy działaniem metod &lt;b&gt;grab&lt;/b&gt; i &lt;b&gt;wraps&lt;/b&gt; jest dość subtelna, ale czasem może okazać się istotna - chodzi mianowicie o strukturę dokumentu po wykonaniu operacji.&lt;/p&gt;
&lt;p&gt;Weźmy teraz pod uwagę następującą strukturę dokumentu:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div id=&quot;test1&quot;&gt;Test 1&lt;/div&gt;
&lt;div id=&quot;test2&quot;&gt;Test 2&lt;/div&gt;
&lt;div id=&quot;test3&quot;&gt;Test 3&lt;/div&gt;
&lt;div id=&quot;test4&quot;&gt;Test 4&lt;/div&gt;
&lt;div id=&quot;test5&quot;&gt;Test 5&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;Jeżeli wykonamy operację:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('test4').grab('test2');{/geshi}&lt;/p&gt;
&lt;p&gt;Otrzymamy rezultat postaci:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div id=&quot;test1&quot;&gt;Test 1&lt;/div&gt;
&lt;div id=&quot;test3&quot;&gt;Test 3&lt;/div&gt;
&lt;div id=&quot;test4&quot;&gt;Test 4
&lt;div id=&quot;test2&quot;&gt;Test 2&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;test5&quot;&gt;Test 5&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;Gdybyśmy teraz wykonali to samo, ale z użyciem metody &lt;b&gt;wraps&lt;/b&gt; na początkowo wspomnianej strukturze:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('test4').wraps('test2');{/geshi}&lt;/p&gt;
&lt;p&gt;To otrzymamy:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div id=&quot;test1&quot;&gt;Test 1&lt;/div&gt;
&lt;div id=&quot;test4&quot;&gt;Test 4
&lt;div id=&quot;test2&quot;&gt;Test 2&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;test3&quot;&gt;Test 3&lt;/div&gt;
&lt;div id=&quot;test5&quot;&gt;Test 5&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;Jak widać różnica pomiędzy tymi metodami polega na tym, że metoda &lt;b&gt;wraps&lt;/b&gt; &quot;owija&quot; element rodzica wokół potomka, a metoda &lt;b&gt;grab&lt;/b&gt; umieszcza potomka w elemencie rodzica. W rezultacie otrzymujemy dwa zupełnie inne rezultaty na stronie.&lt;/p&gt;
&lt;h3&gt;Dla treningu&lt;/h3&gt;
&lt;p&gt;Tym razem ciekawsze zadanie - proponuję ulepszyć naszą implementację listy tak by była ona wielopoziomowa - każdy z jej elementów może stać się elementem nadrzędnym osobnej listy. Aby uzyskać taki efekt warto zastanowić się nad użyciem metod &lt;b&gt;grab&lt;/b&gt; i &lt;b&gt;adopt&lt;/b&gt;. Zasada jest taka, że każdy element posiada dodatkowy przycisk do tworzenia podlisty (tworzenie podlisty polega na stworzeniu w danym elemencie kolejnej listy nieuporządkowanej tak by można się było do niej potem łatwo odwołać - tutaj można wykorzystać selektory lub metody &lt;b&gt;set&lt;/b&gt; i &lt;b&gt;get&lt;/b&gt; do przechowywania stosownych informacji). Dodatkowo pierwszy i ostatni element listy posiadałyby specjalne przyciski, które pozwalają umieścić je poziom wyżej z tym, że pierwszy element umieszczany by był przed listą z której pochodzi, a ostatni - za nią. Oczywiście należy pamiętać o ukrywaniu stosownych przycisków w określonym momencie - na przykład w momencie gdy dany element nie jest już pierwszym lub ostatnim elementem danej listy.&lt;/p&gt;
&lt;h3&gt;Podsumowanie&lt;/h3&gt;
&lt;p&gt;Poznaliśmy metody związane z manipulacją strukturą dokumentu i pozostało nam jeszcze zapoznać się z kilkoma metodami związanymi z klasami elementu oraz kilka metod, których nie można zaklasyfikować do jakiejś szerszej grupy funkcjonalności - to wszystko w kolejnej i ostatniej części kursu poświęconej zagadnieniom związanym z plikiem &lt;b&gt;Element.js&lt;/b&gt;&lt;/p&gt;
</description><pubDate>Sun, 28 Sep 2008 09:55:28 +0200</pubDate><guid>http://blog.dziudek.pl/2008/09/28/mootools-1-2-elementy-strony-cz-3/</guid><category>JavaScript</category><category>mootools</category><category>Techblog</category><category>Webmastering</category></item><item><title>MooTools 1.2 - elementy strony cz. 2</title><link>http://blog.dziudek.pl/2008/09/05/mootools-1-2-elementy-strony-cz-2/</link><description>&lt;p&gt;W kolejnej części kursu poświęconej elementom strony, zajmiemy się dynamicznym tworzeniem elementów, zmienianiem ich atrybutów oraz zapoznamy się z zupełnie nową funkcjonalnością klasy &lt;b&gt;Element&lt;/b&gt; - możliwością przechowywania informacji w obiektach tej klasy.&lt;/p&gt;
&lt;h3&gt;Tworzenie elementów&lt;/h3&gt;
&lt;p&gt;Prędzej czy później podczas tworzenia bardziej złożonego skryptu JavaScript zachodzi potrzeba stworzenia zupełnie nowego elementu &quot;w locie&quot;. W MooTools wystarczy stworzyć nowy obiekt klasy &lt;b&gt;Element&lt;/b&gt; z podanym jednym argumentem - typem elementu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div');{/geshi}&lt;/p&gt;
&lt;p&gt;Jest to najprostszy przykład użycia konstruktora elementów. Ma on jednak o wiele bardziej rozbudowane możliwości - możemy określić zawartość poszczególnych atrybutów danego elementu - dokonujemy tego dzięki obiektowi podanemu jaki drugi argument konstruktora:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy' });{/geshi}&lt;/p&gt;
&lt;p&gt;Dodatkowo możemy określić styl elementu w obiekcie &lt;b&gt;style&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' } });{/geshi}&lt;/p&gt;
&lt;p&gt;Istnieją jeszcze trzy parametry do określenia - zawartość elementu możemy określić poprzez właściwości &lt;b&gt;text&lt;/b&gt; lub &lt;b&gt;html&lt;/b&gt; - różnica oczywiście polega na tym, że z pierwszej z nich korzystamy dodając tylko tekst, a z drugiej podczas dodawania tekstu z kodem (X)HTML:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst' });{/geshi}{geshi lang=javascript}var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'html': '&lt;strong&gt;przykładowy pogrubiony tekst&lt;/strong&gt;' });{/geshi}&lt;/p&gt;
&lt;p&gt;Ostatnia właściwość to &lt;b&gt;events&lt;/b&gt; - pozwala od razu określić zdarzenia elementu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst', 'events': { 'click': function(){ // kod zdarzenia onclick }, 'mouseenter': function(){ // kod zdarzenia onmouseenter }, 'mouseleave': function(){ // kod zdarzenia onmouseleave } } });{/geshi}&lt;/p&gt;
&lt;p&gt;Jak widać można całkiem spory kawałek kodu wygenerować dla stworzenia pojedynczego elementu z zawartością i zdarzeniami.&lt;/p&gt;
&lt;p&gt;Konstruowaniem nowych elementów zajmiemy się poważniej przy okazji następnej części poświęconej elementom strony i m.in. metodzie &lt;b&gt;inject&lt;/b&gt;. Warto jednak zwrócić uwagę na pewne podobieństwo konstruktora elementu do metody set.&lt;/p&gt;
&lt;h3&gt;Set i get&lt;/h3&gt;
&lt;p&gt;Każdemu obiektowi klasy &lt;b&gt;Element&lt;/b&gt; możemy określić wartości poszczególnych cech za pomocą metody &lt;b&gt;set&lt;/b&gt;. Możemy to robić pojedynczo:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').set('class','nowaKlasa');{/geshi}&lt;/p&gt;
&lt;p&gt;Lub ustawiać kilka właściwości naraz podając jako argument tej metody obiekt podobny do obiektu będącego drugim argumentem konstruktora. Zatem zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div',{ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst', 'events': { 'click': function(){ // kod zdarzenia onclick }, 'mouseenter': function(){ // kod zdarzenia onmouseenter }, 'mouseleave': function(){ // kod zdarzenia onmouseleave } } });{/geshi}&lt;/p&gt;
&lt;p&gt;moglibyśmy zapisać również jako:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var nowyDiv = new Element('div') nowyDiv.set({ 'class':'testowy', 'id':'pierwszy', 'style' : { 'background': '#EEE', 'color': '#777' }, 'text': 'przykładowy tekst', 'events': { 'click': function(){ // kod zdarzenia onclick }, 'mouseenter': function(){ // kod zdarzenia onmouseenter }, 'mouseleave': function(){ // kod zdarzenia onmouseleave } } });{/geshi}&lt;/p&gt;
&lt;p&gt;Warto jeszcze wiedzieć, że w wypadku właściwości &lt;b&gt;html&lt;/b&gt; i metody &lt;b&gt;set&lt;/b&gt;, możemy jako argumenty podać kilka łańcuchów kodu (x)HTML:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').set('html','&lt;em&gt;tekst&lt;/em&gt;','&lt;strong&gt;tekst&lt;/strong&gt;');{/geshi}&lt;/p&gt;
&lt;p&gt;W powyższym wypadku zostaną dodane dwa teksty do elementu - kursywa i pogrubienie.&lt;/p&gt;
&lt;p&gt;Gdybyśmy potrzebowali pobrać wartości poszczególnych właściwości wystarczy wykorzystać metodę &lt;b&gt;get&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').get('class');{/geshi}&lt;/p&gt;
&lt;p&gt;Możemy też pobrać typ elementu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').get('tag');{/geshi}&lt;/p&gt;
&lt;p&gt;Powyższy kod zwróci nam na przykład wartość '&lt;em&gt;div&lt;/em&gt;' jeżeli dany element jest divem.&lt;/p&gt;
&lt;p&gt;Od razu uprzedzam, że zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').set('tag','strong');{/geshi}&lt;/p&gt;
&lt;p&gt;Nie zamieni diva w pogrubienie - doda po prostu atrybut &lt;b&gt;tag&lt;/b&gt; do tego elementu o wartości &lt;b&gt;strong&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Warto jeszcze wiedzieć, że do czyszczenia danej właściwości służy metoda &lt;b&gt;erase&lt;/b&gt;, która ma składnię podobną do metody &lt;b&gt;get&lt;/b&gt; - pobiera nazwę właściwości do wyczyszczenia, zatem zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').erase('id');{/geshi}&lt;/p&gt;
&lt;p&gt;Wyczyści atrybut &lt;b&gt;id&lt;/b&gt; naszego elementu i uniemożliwi kolejne odwołania do niego poprzez selektor:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy'){/geshi}&lt;/p&gt;
&lt;h3&gt;Własne set, get i erase&lt;/h3&gt;
&lt;p&gt;MooTools udostępnia nam obiekt, który pozwala nam określić własne implementacje metod &lt;b&gt;set&lt;/b&gt;, &lt;b&gt;get&lt;/b&gt; oraz &lt;b&gt;erase&lt;/b&gt; dla danej właściwości - &lt;b&gt;Element.Properties&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Przykładowo dla właściwości &lt;b&gt;html&lt;/b&gt; metoda &lt;b&gt;set&lt;/b&gt; wygląda następująco:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}Element.Properties.html = { set: function(){ return this.innerHTML = Array.flatten(arguments).join(''); } };{/geshi}&lt;/p&gt;
&lt;p&gt;Jest to o tyle przydatna funkcjonalność, że możemy zmienić obsługę poszczególnych właściwości na wygodniejszą dla nas. Koncepcje wykorzystania pozostawiam Wam - kilka możecie znaleźć w kodzie źródłowym MooTools :)&lt;/p&gt;
&lt;h3&gt;Zawężamy zakres działań&lt;/h3&gt;
&lt;p&gt;Metody &lt;b&gt;get&lt;/b&gt;, &lt;b&gt;set&lt;/b&gt; i &lt;b&gt;erase&lt;/b&gt; dają nam dostęp do wszystkich najważniejszych cech elementu - jego zdarzeń, stylu i atrybutów. Gdybyśmy jednak chcieli się ograniczyć tylko do atrybutów elementu to mamy do dyspozycji sześć metod będących odpowiednikami metod &lt;b&gt;get&lt;/b&gt;, &lt;b&gt;set&lt;/b&gt; i &lt;b&gt;erase&lt;/b&gt;. Każda z tych metod ma swój odpowiednik podobnie jak &lt;b&gt;$&lt;/b&gt; i &lt;b&gt;$$&lt;/b&gt; czy &lt;b&gt;getElement&lt;/b&gt; i &lt;b&gt;getElements&lt;/b&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;getProperty,&lt;/li&gt;
&lt;li&gt;getProperties,&lt;/li&gt;
&lt;li&gt;setProperty,&lt;/li&gt;
&lt;li&gt;setProperties,&lt;/li&gt;
&lt;li&gt;removeProperty,&lt;/li&gt;
&lt;li&gt;removeProperties&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Składnia tych metod nie jest skomplikowana - pobranie pojedynczego atrybutu wymaga zapisu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').getProperty('class');{/geshi}&lt;/p&gt;
&lt;p&gt;Natomiast pobranie wartości kilku atrybutów naraz wymaga podania po prostu większej liczby argumentów:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').getProperties('class', 'title');{/geshi}&lt;/p&gt;
&lt;p&gt;Warto przy tym pamiętać, że &lt;b&gt;getProperty&lt;/b&gt; zwraca po prostu wartość atrybutu, a &lt;b&gt;getProperties&lt;/b&gt; zwraca obiekt postaci:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}{ 'class' : 'nazwaKlasy', 'title' : 'tytulElementu' }{/geshi}&lt;/p&gt;
&lt;p&gt;Metoda &lt;b&gt;setProperty&lt;/b&gt; ma składnię podobną do metody &lt;b&gt;getProperty&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').setProperty('class', 'nazwaKlasy');{/geshi}&lt;/p&gt;
&lt;p&gt;Natomiast metoda &lt;b&gt;setProperties&lt;/b&gt; pobiera jako argument &lt;b&gt;obiekt&lt;/b&gt; - na przykład taki jak ten zwracany przez metodę &lt;b&gt;getProperties&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').setProperties({ 'class' : 'nazwaKlasy', 'title' : 'tytulElementu' });{/geshi}&lt;/p&gt;
&lt;p&gt;Jeżeli chodzi o metody &lt;b&gt;removeProperty&lt;/b&gt; i &lt;b&gt;removeProperties&lt;/b&gt; to składniowo przypominają metody &lt;b&gt;getProperty&lt;/b&gt; i &lt;b&gt;getProperties&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').removeProperty('class'); $('testowy').removeProperties('class', 'title');{/geshi}&lt;/p&gt;
&lt;p&gt;Kilka z tych metod wykorzystamy w przykładzie do tej części kursu.&lt;/p&gt;
&lt;h3&gt;Gdy potrzeba przechować coś więcej&lt;/h3&gt;
&lt;p&gt;Najciekawszą nowością w MooTools 1.2 jeżeli chodzi o właściwości elementów są metody &lt;b&gt;store&lt;/b&gt; i &lt;b&gt;retrieve&lt;/b&gt;. Ileż to razy przydałoby się przechować jakieś informacje o elemencie ? Wcześniej z reguły można było kombinować z tablicami asocjacyjnymi, ukrywaniem danych w dostępnych atrybutach elementu itd. A teraz wystarczy zapisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').store('jakasCecha', 'jakasWartosc');{/geshi}&lt;/p&gt;
&lt;p&gt;I już mamy przechowaną wartość w elemencie - możemy ją odczytać poprzez zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$('testowy').retrieve('jakasCecha');{/geshi}&lt;/p&gt;
&lt;p&gt;Dla przykładu stworzymy sobie prosty licznik kliknięć w wybrane elementy strony.&lt;/p&gt;
&lt;p&gt;Niech wszystkie elementy dla których mają być zliczane kliknięcia mają jedną cechę wspólną - klasę &lt;b&gt;storage&lt;/b&gt;. To na jej podstawie będziemy dokonywali selekcji tych elementów dla celów statystycznych oraz będziemy korzystać z tej cechy w obserwatorze zdarzenia &lt;b&gt;onclick&lt;/b&gt; dotyczącym całego dokumentu. Informacje będzie przechowywała cecha o nazwie &lt;b&gt;clickCounter&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Na początek zainicjalizujemy pierwszą wartość - zero dla naszej cechy we wszystkich elementach z klasą &lt;b&gt;storage&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ $$('.storage').each(function(el){ el.store('clickCounter', 0); }); });{/geshi}&lt;/p&gt;
&lt;p&gt;Do tego musimy dodać stosowny obserwator zdarzenia &lt;b&gt;onclick&lt;/b&gt;, który do każdego kliknięcia elementu klasy &lt;b&gt;storage&lt;/b&gt; doda operację zwiększenia wartości &lt;b&gt;clickCounter&lt;/b&gt; o jeden:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ $$('.storage').each(function(el){ el.store('clickCounter', 0); }); document.body.addEvent(&quot;click&quot;, function(event){ var elmt = new Event(event).target; if(elmt.getProperty('class') == 'storage'){ var counter = elmt.retrieve('clickCounter'); counter++; elmt.store('clickCounter', counter); } }); });{/geshi}&lt;/p&gt;
&lt;p&gt;Ostatnia ważna sprawa to prezentacja statystyk kliknięć. Ja proponuję by znalazły się one w divie z listą nieuporządkowaną, której pozycje będą prezentowały typ elementu i jego atrybut id oraz ilość kliknięć w postaci :&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}typ#idElementu - ilość Kliknięć{/geshi}&lt;/p&gt;
&lt;p&gt;Dane będą aktualizowane za pomocą funkcji &lt;b&gt;stats&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}function stats(){ var statContent = ''; $$('.storage').each(function(el){ statContent += '&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;' + el.get('tag') + '#' + el.get('id') + ' - ' + el.retrieve('clickCounter') + '&lt;/li&gt;
&lt;li style=&quot;list-style: none&quot;&gt;'; }); $('stats').set('html', statContent); }{/geshi}&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oczywiście wywołanie tej funkcji umieszczamy w kodzie obserwatora zdarzenia &lt;b&gt;onclick&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ $$('.storage').each(function(el){ el.store('clickCounter', 0); }); document.body.addEvent(&quot;click&quot;, function(event){ var elmt = new Event(event).target; if(elmt.getProperty('class') == 'storage'){ var counter = elmt.retrieve('clickCounter'); counter++; elmt.store('clickCounter', counter); stats(); // &amp;lt;-- wywołanie funkcji stats } }); stats(); // pierwsze wywołanie dla zainicjalizowania });{/geshi}&lt;/p&gt;
&lt;p&gt;Cały powyższy przykład w akcji:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dziudek.dreamhosters.com/mootools12/examples/8/mootools8.html&quot;&gt;PRZYKŁAD&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Dla treningu&lt;/h3&gt;
&lt;p&gt;W ramach utrwalenie sobie poznanych metod klasy &lt;b&gt;Element&lt;/b&gt; proponuję stworzyć dwa skrypty:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zmieniający atrybuty &lt;b&gt;href&lt;/b&gt; oraz &lt;b&gt;title&lt;/b&gt; linka znajdującego się pod trzema obrazkami - zmiana atrybutów ma następować po kliknięciu na dany obrazek - link ma zmieniać swoje cechy tak by dopasować je do obrazka,&lt;/li&gt;
&lt;li&gt;Skrypt powiązany z prostą wyszukiwarką na stronie (zwykły &lt;b&gt;input&lt;/b&gt; typu &lt;b&gt;text&lt;/b&gt; oraz przycisk &quot;&lt;em&gt;Szukaj&lt;/em&gt;&quot;) zawierającej kilka obrazków, który sprawi, że po kliknięciu przycisku &quot;&lt;em&gt;Szukaj&lt;/em&gt;&quot; nastąpi przeszukanie atrybutów &lt;b&gt;title&lt;/b&gt; wszystkich obrazków i zmianę klasy obrazka na inną w momencie wykrycia danej frazy w atrybucie &lt;b&gt;title&lt;/b&gt; obrazka. Opcjonalnie można rozbudować &quot;wyszukiwarkę&quot; tak by wyszukiwała tylko wśród obrazków oznaczonych odpowiednią klasą - na przykład do obrazków o rozmiarach mniejszych niż określone (atrybuty &lt;b&gt;width&lt;/b&gt; i &lt;b&gt;height&lt;/b&gt;) byłaby dodawana klasa &lt;b&gt;small&lt;/b&gt;, a pozostałym klasa &lt;b&gt;big&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Podsumowanie&lt;/h3&gt;
&lt;p&gt;Wiemy już jak tworzyć nowe elementy dokumentu, jak operować na większości cech elementu, a także jak wykorzystywać elementy do przechowywania danych. W kolejnej części kursu zajmiemy się głównie umieszczaniem elementów w dokumencie ich niszczeniem, a także zajmiemy się elementem &lt;b&gt;iframe&lt;/b&gt;.&lt;/p&gt;
</description><pubDate>Fri, 05 Sep 2008 20:21:38 +0200</pubDate><guid>http://blog.dziudek.pl/2008/09/05/mootools-1-2-elementy-strony-cz-2/</guid><category>JavaScript</category><category>mootools</category><category>Techblog</category><category>Webmastering</category></item><item><title>Dla tych co tęsknią za $E i $ES</title><link>http://blog.dziudek.pl/2008/09/04/dla-tych-co-tesknia-za-e-i-es/</link><description>&lt;p&gt;W MooTools 1.2 usunięto funkcje, które stosowałem dość często - &lt;b&gt;$E&lt;/b&gt; i &lt;b&gt;$ES&lt;/b&gt;. Pozwalały one wybrać odpowiednio pierwszy lub wszystkie elementy zgodne z podanym selektorem i znajdujące się w podanym elemencie. Były one swoistym skrótem dla metod &lt;b&gt;getElementsBySelector&lt;/b&gt;, &lt;b&gt;getElement&lt;/b&gt; i &lt;b&gt;getElements&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Gdyby ktoś chciał jednak móc je zastosować to prezentuję poniżej ich implementacje w MooTools 1.2:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}function $E(selector, scope){ return $($defined(scope) ? scope : document.body).getElement(selector); } function $ES(selector, scope){ return $($defined(scope) ? scope : document.body).getElements(selector); }{/geshi}&lt;/p&gt;
&lt;p&gt;Pierwszy argument to oczywiście selektor określający jakie elementy chcemy wyselekcjonować, a drugi argument jest opcjonalny i pozwala ograniczyć zakres poszukiwań do wybranego elementu - musi to być uchwyt do elementu lub jego &lt;b&gt;id&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Dla tych, którzy chcieliby w drugim argumencie móc zastosować także selektor przygotowałem lekko zmienioną wersję funkcji $E i $ES pozwalającą stosować w obu argumentach selektory:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}function $E(selector, scope){ return $$($defined(scope) ? scope : document.body)[0].getElement(selector); } function $ES(selector, scope){ return $$($defined(scope) ? scope : document.body)[0].getElements(selector); }{/geshi}&lt;/p&gt;
&lt;p&gt;Należy pamiętać, że w tym wypadku nie można podać &lt;b&gt;id&lt;/b&gt; bez znaku &lt;b&gt;#&lt;/b&gt; na początku.&lt;/p&gt;
</description><pubDate>Thu, 04 Sep 2008 20:14:43 +0200</pubDate><guid>http://blog.dziudek.pl/2008/09/04/dla-tych-co-tesknia-za-e-i-es/</guid><category>JavaScript</category><category>mootools</category><category>Techblog</category><category>Webmastering</category></item><item><title>MooTools 1.2 - elementy strony cz. 1</title><link>http://blog.dziudek.pl/2008/09/03/mootools-1-2-elementy-strony-cz-1/</link><description>&lt;p&gt;Niezwykle istotną sprawą przy tworzeniu skryptów jest możliwość łatwego poruszania się po drzewie dokumentu - w MooTools mamy kilka metod, które pozwalają nam na dostęp do różnych elementów względem innych elementów. Dodatkowo zapoznamy się bliżej z funkcją &lt;b&gt;$$&lt;/b&gt;, która pozwala na selekcję kilku elementów naraz według określonych parametrów.&lt;/p&gt;
&lt;h3&gt;Dolary&lt;/h3&gt;
&lt;p&gt;Jak wiemy funkcja &lt;b&gt;$&lt;/b&gt; pozwala przede wszystkim na selekcję pojedynczego elementu według jego atrybutu &lt;b&gt;id&lt;/b&gt;. W wypadku funkcji &lt;b&gt;$$&lt;/b&gt; możemy wyselekcjonować całe grupy elementów. W podstawowej wersji możemy dokonywać selekcji według tagów natomiast po dodaniu obsługi selektorów do frameworka możemy korzystać także z selektorów CSS. Zatem aby uzyskać dostęp do wszystkich obrazków na stronie zapiszemy:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$$('img');{/geshi}&lt;/p&gt;
&lt;p&gt;Aby wybrać tylko obrazki posiadające klasę &lt;b&gt;image&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$$('img.image');{/geshi}&lt;/p&gt;
&lt;p&gt;Dodatkowo możemy stworzyć grupę elementów złożoną z kilku typów elementów - przykładowo aby wybrać wszystkie obrazki ze strony i linki z klasą link, zapisujemy:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$$('img', 'a.link');{/geshi}&lt;/p&gt;
&lt;p&gt;Zatem jako kolejne argumenty możemy podawać kolejne selektory elementów. Dodatkowo jeżeli musimy wykonać jakąś operację na danym elemencie do którego mamy już uchwyt w postaci zmiennej i grupie innych elementów, które należy dopiero wyselekcjonować zapiszemy:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var el = $('element'); // fragment kodu $$(el, 'img');{/geshi}&lt;/p&gt;
&lt;p&gt;Powyższy kod spowoduje stworzenie tablicy wszystkich obrazków ze strony i elementu posiadającego &lt;b&gt;id&lt;/b&gt; &quot;&lt;em&gt;element&lt;/em&gt;&quot;. Jest to zdecydowane ułatwienie - nie musimy do kolekcji elementów dodawać w dalszym kodzie nowej pozycji lub tworzyć jakichś cech wspólnych dla danych elementów tylko po to by ułatwić sobie później selekcję w JavaScript.&lt;/p&gt;
&lt;p&gt;Możliwości funkcji &lt;b&gt;$$&lt;/b&gt; są ogromne, ale prawdziwy ich urok poznamy dopiero przy omawianiu selektorów w dalszej części kursu.&lt;/p&gt;
&lt;h3&gt;Dolary inaczej&lt;/h3&gt;
&lt;p&gt;Swego rodzaju odpowiednikami funkcji &lt;b&gt;$&lt;/b&gt; i &lt;b&gt;$$&lt;/b&gt; są metody &lt;b&gt;getElement&lt;/b&gt;, &lt;b&gt;getElements&lt;/b&gt; oraz &lt;b&gt;getElementById&lt;/b&gt;. Różnica polega na tym, że pozwalają na selekcję tylko jednej grupy elementów - zatem zapis taki jak:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$$('img', 'a.link');{/geshi}&lt;/p&gt;
&lt;p&gt;Jest niemożliwy. Ale metody te mają inną zaletę - pozwalają na selekcję w obrębie danego elementu. Zatem zamiast stosować selektor:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}$$('#testowy a.link');{/geshi}&lt;/p&gt;
&lt;p&gt;Możemy wykorzystać zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var el = $('testowy'); el.getElements('a.link');{/geshi}&lt;/p&gt;
&lt;p&gt;Oczywiście zapis jest dłuższy, ale za to pozwala na stosowanie prostszych selektorów, a także wygląda w kodzie bardziej logicznie przy pętlach wykonujących selekcję elementów potomnych z kilku elementów. Metoda &lt;b&gt;getElement&lt;/b&gt; różni się od &lt;b&gt;getElements&lt;/b&gt; tym, że zwraca pierwszy element z całej kolekcji. Zatem jeżeli interesowałby nas tylko pierwszy link z klasą link w elemencie posiadającym &lt;b&gt;id&lt;/b&gt; &quot;&lt;em&gt;testowy&lt;/em&gt;&quot; zapiszemy:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var el = $('testowy'); el.getElement('a.link');{/geshi}&lt;/p&gt;
&lt;p&gt;Jeżeli chodzi o metodę &lt;b&gt;getElementById&lt;/b&gt; to powstała ona po to by uzupełnić funkcjonalność natywnej metody obiektu &lt;b&gt;document&lt;/b&gt; związanej z DOM - &lt;b&gt;getElementById&lt;/b&gt; pozwala ograniczyć zakres poszukiwań do danego elementu - wydawałoby się, że istnienie takiej metody jest mało sensowne, ponieważ atrybut &lt;b&gt;id&lt;/b&gt; powinien być unikalny, ale metoda ta jest przydatna w sytuacji, gdzie musimy stwierdzić czy element o danym &lt;b&gt;id&lt;/b&gt; jest elementem potomnym innego elementu:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var el = $('testowy'); var result = el.getElementById('link');{/geshi}&lt;/p&gt;
&lt;p&gt;Zmienna result będzie zawierała uchwyt do elementu posiadającego &lt;b&gt;id&lt;/b&gt; &quot;&lt;em&gt;link&lt;/em&gt;&quot;, jeżeli jest on potomkiem elementu posiadającego &lt;b&gt;id&lt;/b&gt; &quot;&lt;i&gt;testowy&lt;/i&gt;&quot; - w innym wypadku otrzymamy wartość &lt;b&gt;null&lt;/b&gt;. Oczywiście można to też zbadać inaczej:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var result = $$('#testowy #link'); {/geshi}&lt;/p&gt;
&lt;p&gt;Jeżeli tablica &lt;b&gt;result&lt;/b&gt; jest pusta to element &quot;&lt;em&gt;link&lt;/em&gt;&quot; nie jest potomkiem elementu &quot;&lt;em&gt;testowy&lt;/em&gt;&quot; - znów wszystko tak naprawdę dotyczy tego jak bardzo złożonych selektorów chcemy używać.&lt;/p&gt;
&lt;p&gt;Dla podsumowania tej części wpisu przykład prezentujący różne rodzaje selekcji elementów wraz z użyciem funkcji i metod:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dziudek.dreamhosters.com/mootools12/examples/5/mootools5.html&quot;&gt;PRZYKŁAD 1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Warto zwrócić uwagę na równoważne zapisy oraz te zapisy, które nie zwracają żadnych elementów.&lt;/p&gt;
&lt;h3&gt;Bądź punktem odniesienia&lt;/h3&gt;
&lt;p&gt;Teraz chciałbym omówić metody, które pozwalają dokonywać selekcji elementów względem innego elementu w zakresie elementów sąsiednich, nadrzędnych i potomnych.&lt;/p&gt;
&lt;p&gt;Na początek warto zapamiętać sobie trzy najważniejsze cechy wspólne wszystkich metod, które za chwilę omówię - jako argument mogą one opcjonalnie przyjmować typ elementu - zatem możemy dokładnie zdefiniować czego szukamy, zwłaszcza w momencie gdy mamy do dyspozycji rozbudowane selektory CSS. Druga cecha to fakt, że dla wszystkich rodzajów operacji istnieją zawsze dwa rodzaje selekcji - analogiczne do funkcji &lt;b&gt;$&lt;/b&gt; i &lt;b&gt;$$&lt;/b&gt;. Zatem jedna metoda dokonuje selekcji pojedynczego elementu, a druga zwraca kolekcję elementów. Trzecia cecha - jeżeli element jaki chcieliśmy uzyskać nie istnieje to każda z tych metod zwraca wartość &lt;b&gt;null&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Zacznijmy od wykrywania elementów nadrzędnych - do dyspozycji mamy metody &lt;b&gt;getParent&lt;/b&gt; i &lt;b&gt;getParents&lt;/b&gt; - już same nazwy mówią, która metoda jest odpowiednikiem funkcji &lt;b&gt;$&lt;/b&gt;, a która odpowiednikiem funkcji &lt;b&gt;$$&lt;/b&gt;. Zatem aby wykryć element nadrzędny wystarczy zapisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParent();{/geshi}&lt;/p&gt;
&lt;p&gt;Mając strukturę:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div&gt;&lt;a href=&quot;http://blog.dziudek.pl&quot;&gt;Link&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;I przyjmując, że zmienna &lt;b&gt;element&lt;/b&gt; jest uchwytem do linka, uzyskalibyśmy uchwyt do elementu &lt;b&gt;div&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Możemy też stworzyć taką strukturę elementów jak poniższa:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.dziudek.pl&quot;&gt;Link 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://miniblog.dziudek.pl&quot;&gt;Link 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;Aby uzyskać uchwyty do elementów &lt;b&gt;li&lt;/b&gt;, &lt;b&gt;ul&lt;/b&gt; i &lt;b&gt;div&lt;/b&gt; wystarczy zapisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParents();{/geshi}&lt;/p&gt;
&lt;p&gt;Gdzie zmienna &lt;b&gt;element&lt;/b&gt; odnosi się do pierwszego lub drugiego linka.&lt;/p&gt;
&lt;p&gt;To były podstawowe możliwości tych metod - a gdybyśmy chcieli szybko uzyskać uchwyt do elementu &lt;b&gt;div&lt;/b&gt; z poziomu linka ?&lt;/p&gt;
&lt;p&gt;W &quot;starym&quot; MooTools 1.11 musielibyśmy zapisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParent().getParent().getParent();{/geshi}&lt;/p&gt;
&lt;p&gt;A w naszym wypadku możemy zapisać:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParents()[2];{/geshi}&lt;/p&gt;
&lt;p&gt;Lub:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParent('div');{/geshi}&lt;/p&gt;
&lt;p&gt;Nie będę ukrywał, że drugi zapis jest o wiele bardziej elastyczny - przede wszystkim mamy pewność, że uzyskamy uchwyt do pierwszego nadrzędnego elementu typu div - możliwości jakie daje ten jeden niepozorny parametr we wszystkich funkcjach tego typu proszę przeanalizować samemu - na pewno w wielu wypadkach ułatwiają życie oraz często skracają kod skryptu.&lt;/p&gt;
&lt;p&gt;Oczywiście w naszym wypadku zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParent('div');{/geshi}&lt;/p&gt;
&lt;p&gt;Jest równoznaczny z zapisem:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getParents('div'); {/geshi}&lt;/p&gt;
&lt;p&gt;Ale w wypadku bardziej rozbudowanej witryny drugi zapis może zwrócić więcej elementów nadrzędnych typu &lt;b&gt;div&lt;/b&gt;.&lt;/p&gt;
&lt;h3&gt;Pora na dzieci&lt;/h3&gt;
&lt;p&gt;Wiemy już jak odnaleźć rodziców naszego elementu - a co z dziećmi (potomkami) ? Istnieje metoda &lt;b&gt;getChildren&lt;/b&gt;, która wyjątkowo nie ma odpowiednika &lt;b&gt;getChild&lt;/b&gt; - w zamian mamy metody &lt;b&gt;getFirst&lt;/b&gt; oraz &lt;b&gt;getLast&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Metoda &lt;b&gt;getChildren&lt;/b&gt; pozwala nam uzyskać kolekcję wszystkich elementów potomnych danego elementu lub tylko tych, które określono w podanym jako argument selektorze. Należy pamiętać, że elementy potomne rozumiemy jako te, które znajdują się bezpośrednio w danym elemencie. Skorzystajmy ze znanej już struktury elementów:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.dziudek.pl&quot;&gt;Link 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://miniblog.dziudek.pl&quot;&gt;Link 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;W tym wypadku element div ma tylko jeden element potomny - listę nieuporządkowaną. I to ona będzie jedynym elementem kolekcji zwracanej przez:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getChildren();{/geshi}&lt;/p&gt;
&lt;p&gt;Gdzie element to oczywiście uchwyt do naszego jedynego diva. Zatem zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getChildren('li');{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróci nam wartość &lt;b&gt;null&lt;/b&gt;. Gdybyśmy teraz zmienną element zdefiniowali jako:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}var element = $$('ul')[0];{/geshi}&lt;/p&gt;
&lt;p&gt;I wykorzystali metody &lt;b&gt;getFirst&lt;/b&gt; i &lt;b&gt;getLast&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getFirst(); element.getLast();{/geshi}&lt;/p&gt;
&lt;p&gt;To uzyskalibyśmy dostęp odpowiednio do pierwszej i ostatniej pozycji listy nieuporządkowanej.&lt;/p&gt;
&lt;p&gt;Zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getFirst().getFirst('b'); element.getLast().getFirst('i');{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróci nam oczywiście wartości &lt;b&gt;null&lt;/b&gt;, ponieważ elementy listy nie zawierają elementów kursywy i pogrubienia.&lt;/p&gt;
&lt;p&gt;W poniższym przykładzie prezentuję kilka metod selekcji z użyciem poznanych dotychczas metod związanych z elementami nadrzędnymi i potomnymi:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dziudek.dreamhosters.com/mootools12/examples/6/mootools6.html&quot;&gt;PRZYKŁAD 2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Warto zwrócić uwagę na odwołanie do tablic elementów oraz auto-iterację.&lt;/p&gt;
&lt;h3&gt;Zostali sąsiedzi&lt;/h3&gt;
&lt;p&gt;Wiemy jak dokonać selekcji elementów położonych o poziom wyżej i niżej - istnieją też metody do selekcji elementów na tym samym poziomie - jedną z nich - &lt;b&gt;getNext&lt;/b&gt; już poznaliśmy przy okazji omawiania zdarzeń elementów. Pozostały nam do omówienia jeszcze metody &lt;b&gt;getAllNext&lt;/b&gt;, &lt;b&gt;getPrevious&lt;/b&gt; oraz &lt;b&gt;getAllPrevious&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;Weźmy pod uwagę następującą strukturę elementów:&lt;/p&gt;
&lt;p&gt;{geshi lang=xml}&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;Tekst 1&lt;/p&gt;
&lt;img src=&quot;obrazek.png&quot; alt=&quot;obrazek&quot;&gt;
&lt;p&gt;Tekst 2&lt;/p&gt;
&lt;p&gt;Tekst 3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pozycja 1&lt;/li&gt;
&lt;li&gt;Pozycja 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;{/geshi}&lt;/p&gt;
&lt;p&gt;Gdybyśmy przyjęli, że naszym punktem odniesienia - zmienną &lt;b&gt;element&lt;/b&gt; jest drugi paragraf tekstu to metoda:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getNext();{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróciłaby nam trzeci paragraf. Ta sama metoda z podanym argumentem:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getNext('ul');{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróci nam uchwyt do listy nieuporządkowanej. A oba te element (trzeci paragraf i listę nieuporządkowaną) naraz zwróci metoda:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getAllNext();{/geshi}&lt;/p&gt;
&lt;p&gt;Z metodą &lt;b&gt;getPrevious&lt;/b&gt; jest dokładnie na odwrót (działa &quot;w górę&quot;), zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getPrevious();{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróci nam uchwyt do obrazka, a zapis:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getPrevious('p');{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróci nam pierwszy paragraf. No i oczywiście zapis :&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}element.getAllPrevious();{/geshi}&lt;/p&gt;
&lt;p&gt;Zwróci nam oba te elementy (obrazek i pierwszy paragraf tekstu) naraz.&lt;/p&gt;
&lt;p&gt;Celowo nie rozwodziłem się nad tymi metodami, ponieważ są one w swoich założeniach łudząco podobne do poznanych już metod - operują jedynie na innych poziomach elementów z otoczenia naszego punktu odniesienia jakim jest element wskazywany przez zmienną element.&lt;/p&gt;
&lt;p&gt;Kilka przykładów selekcji umieściłem w poniższym przykładzie:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dziudek.dreamhosters.com/mootools12/examples/7/mootools7.html&quot;&gt;PRZYKŁAD 3&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;W ramach treningu&lt;/h3&gt;
&lt;p&gt;Proponuję przygotować zestaw odpowiedników poznanych metod działających jako samodzielne funkcje:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;getParent - $P,&lt;/li&gt;
&lt;li&gt;getParents - $PS,&lt;/li&gt;
&lt;li&gt;getChildren - $C&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Należy pamiętać by uwzględnić fakt, że drugi argument (&lt;b&gt;scope&lt;/b&gt;) jest w tych funkcjach jak najbardziej pożądany (no może poza funkcją &lt;b&gt;getChildren&lt;/b&gt;). Do tego proponuję napisać funkcje:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$I - selekcjonująca obrazki z dokumentu (opcjonalnie argument ograniczający zakres selekcji),&lt;/li&gt;
&lt;li&gt;$F -selekcjonująca formularze z dokumentu (opcjonalnie argument ograniczający zakres selekcji)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Podsumowanie&lt;/h3&gt;
&lt;p&gt;Wiemy już jak poruszać się po drzewie dokumentu, a nawet można by powiedzieć, że potrafimy po nim swobodnie skakać :) W następnej części poświęconej elementom dokumentu zajmiemy się atrybutami elementu i nowościami jakie pojawiły się w MooTools 1.2 w zakresie przechowywania informacji w elementach.&lt;/p&gt;
</description><pubDate>Wed, 03 Sep 2008 23:02:09 +0200</pubDate><guid>http://blog.dziudek.pl/2008/09/03/mootools-1-2-elementy-strony-cz-1/</guid><category>JavaScript</category><category>mootools</category><category>Techblog</category><category>Webmastering</category></item><item><title>String.toHash()</title><link>http://blog.dziudek.pl/2008/09/01/string-tohash/</link><description>&lt;p&gt;Pewnie komuś się przyda metoda odwrotna to metody obiektu &lt;b&gt;Hash&lt;/b&gt; - &lt;b&gt;toQueryString&lt;/b&gt;, czyli metoda obiektu &lt;b&gt;String&lt;/b&gt; - &lt;b&gt;toHash&lt;/b&gt;:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript} String.implement({ toHash: function(){ var hash = new Hash(); this.split('&amp;amp;').each(function(el){ var t = el.split('='); hash.include(t[0], t[1]); }); return hash; } }); {/geshi}&lt;/p&gt;
</description><pubDate>Mon, 01 Sep 2008 16:59:11 +0200</pubDate><guid>http://blog.dziudek.pl/2008/09/01/string-tohash/</guid><category>JavaScript</category><category>mootools</category><category>Webmastering</category></item><item><title>Los bywa złośliwy</title><link>http://blog.dziudek.pl/2008/09/01/los-bywa-zlosliwy/</link><description>&lt;p&gt;Co tu dużo mówić - partycje recovery na laptopach to pomyłka. Jak ktoś nie wie jak sobie poradzić gdy one zawiodą to zostaje tylko serwis - i pożegnanie ze sprzętem na dłuższy czas... No chyba, że komuś nie zależy na posiadaniu systemu za który zapłacił kupując laptopa...&lt;/p&gt;
&lt;p&gt;P.S.: Jakby ktoś się stęsknił za kursem MooTools to informuję, że wróci :) Ciężki sierpień miałem i nie było za bardzo czasu na nic poza pracą, ale ciągle mam nadzieję zdążyć z ukończeniem omówienia MooTools 1.2 (bez pluginów, bo to inna sprawa zupełnie) przed rozpoczęciem kolejnego roku akademickiego :)&lt;/p&gt;
</description><pubDate>Mon, 01 Sep 2008 09:23:05 +0200</pubDate><guid>http://blog.dziudek.pl/2008/09/01/los-bywa-zlosliwy/</guid><category>Ogólne</category></item><item><title>Takie małe usprawnienie do blipa</title><link>http://blog.dziudek.pl/2008/08/16/takie-male-usprawnienie-do-blipa/</link><description>&lt;p&gt;Stworzyłem mały UserJS, który zamienia wszystkie linki do statusów w kokpicie:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://dziudek.dreamhosters.com/site/blip.png&quot; alt=&quot;blip&quot;&gt;&lt;/p&gt;
&lt;p&gt;na przyciski dodające link do treści nowego statusu - &lt;a href=&quot;http://userscripts.org/scripts/show/31823&quot;&gt;Blip easyPermalinks&lt;/a&gt;, może komuś się przyda i ułatwi życie ;)&lt;/p&gt;
</description><pubDate>Sat, 16 Aug 2008 15:06:58 +0200</pubDate><guid>http://blog.dziudek.pl/2008/08/16/takie-male-usprawnienie-do-blipa/</guid><category>JavaScript</category><category>Techblog</category><category>UserJS</category><category>Web 2.0</category><category>Webmastering</category></item><item><title>MooTools 1.2 - zdarzenie DOMContentLoaded</title><link>http://blog.dziudek.pl/2008/08/14/mootools-1-2-zdarzenie-domcontentloaded/</link><description>&lt;p&gt;Każdy kto programował w JavaScript przyzwyczaił się zapewne do zdarzenia &lt;b&gt;onLoad&lt;/b&gt; występującego w momencie załadowania się danej strony WWW. Z reguły wraz z tym zdarzeniem swoje działanie rozpoczynały wszelkie skrypty &lt;abbr title=&quot;JavaScript&quot;&gt;JS&lt;/abbr&gt; związane z &lt;abbr title=&quot;Document Object Model&quot;&gt;DOM&lt;/abbr&gt;, bo wywołanie ich wcześniej niechybnie skończyłoby się błędem związanym z odwoływaniem do elementu, który jeszcze w DOM nie istnieje.&lt;/p&gt;
&lt;h3&gt;Dlaczego używać DomReady ?&lt;/h3&gt;
&lt;p&gt;Nie ma co ukrywać, że w wypadku stron bogatych w grafikę oczekiwanie na wystąpienie zdarzenia &lt;b&gt;onLoad&lt;/b&gt; wymagało cierpliwości (wprost proporcjonalnej do ilości grafiki). Na nasze szczęście stworzono zdarzenie &lt;b&gt;DOMContentLoaded&lt;/b&gt; - występuje ono w momencie załadowania kompletnego drzewa dokumentu - zatem znacznie wcześniej niż zdarzenie &lt;b&gt;onLoad&lt;/b&gt;, bo zdarzenie DOMContentLoaded nie jest zależne od ilości grafiki - w skrajnych wypadkach może więc ono wystąpić kilkanaście sekund przed zdarzeniem &lt;b&gt;onLoad&lt;/b&gt;.&lt;/p&gt;
&lt;h3&gt;Znów ta kompatybilność&lt;/h3&gt;
&lt;p&gt;Żeby nie było tak słodko jak się niektórym wydaje, to muszę tu wspomnieć o tym co jest największą bolączką JS - jak zwykle wszystko zależy od przeglądarki - zdarzenie &lt;b&gt;DOMContentLoaded&lt;/b&gt; zadziała na Firefoksie (i oczywiście wszelkich bazowanych na Gecko przeglądarkach) i Operze (wersje od 9.0 w górę), w wypadku &lt;abbr title=&quot;Internet Explorer&quot;&gt;IE&lt;/abbr&gt; trzeba zastosować &lt;a href=&quot;http://javascript.nwbox.com/IEContentLoaded/&quot;&gt;tą metodę&lt;/a&gt;, natomiast Safari i Konqueror wymagają sprawdzania właściwości &lt;b&gt;document.readyState&lt;/b&gt; (choć ostatnie wersje Safari wspierają natywnie zdarzenie &lt;b&gt;DOMContentLoaded&lt;/b&gt; i kilka innych zdarzeń DOM) - czyli sprawa się ma niewiele lepiej niż w IE. Dociekliwych tego jak to dokładnie działa odsyłam do wpisu &lt;a href=&quot;http://perfectionorvanity.com/2007/05/22/wykonywanie-skryptow-po-zaladowaniu-dom/&quot;&gt;Riddle'a&lt;/a&gt;, który opisał całość dokładnie - ewentualnie można obejrzeć implementacje w MooTools czy jQuery. Całe szczęście, że ilość przeglądarek zupełnie nie mających szansy na obsługę &lt;b&gt;DOMContentLoaded&lt;/b&gt; ociera się o błąd statystyczny (no chyba, że macie dziwną grupę docelową) ;).&lt;/p&gt;
&lt;p&gt;Pora więc pokazać jak to się robi w MooTools:&lt;/p&gt;
&lt;p&gt;{geshi lang=javascript}window.addEvent(&quot;domready&quot;, function(){ // wszystko tutaj wykona się po załadowaniu DOM });{/geshi}&lt;/p&gt;
&lt;p&gt;Powyższy kod to właściwie jeden z tych fragmentów, który pojawia się bardzo często w każdym skrypcie pisanym z użyciem MooTools, dlatego jak ktoś ma słabą pamięć to warto go sobie gdzieś zachować/powiesić na ścianie/[inna forma wspomagania zawodnej pamięci].&lt;/p&gt;
&lt;h3&gt;Dlaczego warto stosować DOMContentLoaded ?&lt;/h3&gt;
&lt;p&gt;Teraz pora na opisanie kilku zastosowań tego cudownego zdarzenia ;)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Czasem w życiu bywa tak, że któraś z nowoczesnych przeglądarek podczas renderowania strony coś psuje - o ile w IE mamy do dyspozycji &lt;b&gt;Expressions&lt;/b&gt; (tu znów odsyłam do &lt;a href=&quot;http://perfectionorvanity.com/2007/01/12/podstawowe-informacje-o-expressions/&quot;&gt;Riddle'a&lt;/a&gt;) w Firefoksie mamy ostatecznie do dyspozycji &lt;abbr title=&quot;Extensible Binding Language&quot;&gt;XBL&lt;/abbr&gt; o tyle dla Opery i Safari nie znam żadnych cudownych metod uzdrawiania tego co wyświetli silnik przeglądarki (a może wiecie coś czego ja nie wiem ? Komentarz mile widziany :). Dlatego też wykorzystując obiekt &lt;b&gt;Browser&lt;/b&gt; możemy stwierdzić z kim mamy do czynienia (z jaką przeglądarką) i poprawić to i owo, a dzięki zdarzeniu &lt;b&gt;DOMContentLoaded&lt;/b&gt;, zmiany pojawią się (z reguły) o wiele wcześniej niż cała strona.&lt;/li&gt;
&lt;li&gt;Nie muszę chyba nikomu mówić, że możliwość wykonania jakiejś operacji przed załadowaniem całej strony (która może być tylko jedną z podstron na drodze do celu) jest dla użytkownika bezcenna - dlatego dodanie zdarzeń do elementów strony zawsze powinno następować jak najszybciej, tak aby użytkownik mógł być pewien, że widząc jakiś przycisk po jego kliknięciu uzyska wykonanie oczekiwanej operacji zamiast braku jakiejkolwiek reakcji.&lt;/li&gt;
&lt;li&gt;W pewnych specyficznych sytuacjach (strony statyczne) możemy symulować takie efekty jak wybór stylu strony - wraz z dokumentem ładujemy wspólną część dla wszystkich styli, a wraz ze zdarzeniem &lt;b&gt;DOMContentLoaded&lt;/b&gt; analizujemy zawartości ciasteczek (Cookies) i na tej podstawie &quot;doładowujemy&quot; (przydatny tu będzie plugin &lt;b&gt;Assets&lt;/b&gt;) dodatkowy, określony przez użytkownika styl. Może całość jest trochę naciągana, ale gdy nie ma żadnego języka server-side pod ręką trzeba sobie jakoś radzić :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Ostrożność to podstawa&lt;/h3&gt;
&lt;p&gt;Na koniec jeszcze jedna istotna uwaga związana ze zdarzeniem &lt;b&gt;DomReady&lt;/b&gt; w MooTools. Zdarzyło mi się kilka przypadków, kiedy to w IE występowały problemy - było to prawdopodobnie związane z dużym stopniem skomplikowania stron na których występował problem. Okazywało się bowiem, że zdarzenie to występowało przed załadowaniem całego drzewa DOM. Co polecam ? W miarę możliwości podczas procesu tworzenia skryptu bazować na zdarzeniu &lt;b&gt;onLoad&lt;/b&gt;, natomiast na sam koniec spróbować je zamienić na zdarzenie &lt;b&gt;DomReady&lt;/b&gt; i dokładnie zbadać zachowanie skryptu w IE. Pozwoli to uniknąć błędów, które można powiedzieć biorą się z kosmosu - skrypt &quot;nie widzi&quot; elementów strony, które są załadowane itp.&lt;/p&gt;
&lt;h3&gt;Podsumowanie&lt;/h3&gt;
&lt;p&gt;O zdarzeniach w MooTools 1.2 wiemy już właściwie wszystko co nam potrzeba - zarówno od strony klasy &lt;b&gt;Element&lt;/b&gt;, jak i od strony klasy &lt;b&gt;Events&lt;/b&gt; i obiektu &lt;b&gt;Event&lt;/b&gt;. W następnych częściach kursu niewątpliwie wykorzystamy tą wiedzę by manipulować strukturą drzewa dokumentu.&lt;/p&gt;
</description><pubDate>Thu, 14 Aug 2008 22:03:16 +0200</pubDate><guid>http://blog.dziudek.pl/2008/08/14/mootools-1-2-zdarzenie-domcontentloaded/</guid><category>JavaScript</category><category>mootools</category><category>Techblog</category><category>Webmastering</category></item></channel></rss>