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

<channel>
	<title>MGdevelop &#187; Webdeveloping</title>
	<atom:link href="http://mgdevelop.pl/index.php/kategoria/webdeveloping/feed/" rel="self" type="application/rss+xml" />
	<link>http://mgdevelop.pl</link>
	<description>Programming is an art form that fights back</description>
	<lastBuildDate>Thu, 07 Jul 2011 16:59:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Uploader plików z wykorzystaniem HTML5</title>
		<link>http://mgdevelop.pl/index.php/2011/06/uploader-plikow-z-wykorzystaniem-html5/</link>
		<comments>http://mgdevelop.pl/index.php/2011/06/uploader-plikow-z-wykorzystaniem-html5/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 17:37:47 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[drag&drop]]></category>
		<category><![CDATA[FileReader]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[plik]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=609</guid>
		<description><![CDATA[Swego czasu problemem dla twórców stron internetowych było wysyłanie plików bez przeładowywania strony. Mieliśmy do wyboru albo użyć apleta flash albo szpecić... <a href="http://mgdevelop.pl/index.php/2011/06/uploader-plikow-z-wykorzystaniem-html5/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Swego czasu problemem dla twórców stron internetowych było wysyłanie plików bez przeładowywania strony. Mieliśmy do wyboru albo użyć <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://www.uploadify.com/">apleta flash</a> albo <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://www.openjs.com/articles/ajax/ajax_file_upload/">szpecić swój kod iframami</a>. Czasy na szczęście się zmieniają i powstają nowe technologie które to pozwalają na coraz więcej. Aktualnie nowoczesne przeglądarki udostępniają obiekt<em>File</em> z poziomu kodu JS który w połączeniu z ajaxem pozwala stworzyć uploader plików dorównujący możliwościami tym flashowym lub javowym.<span id="more-609"></span></p>
<h1>Stawiamy cele</h1>
<p>Najpierw postaram się omówić co będę chciał zbudować w tym tutorialu. Moim celem jest napisanie uploadera który będzie w przeglądarkach Chrome i Firefox zastępować tradycyjny HTMLowy formularz. Nasz skrypt bedzie przyjmował pliki metodą <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://pl.wikipedia.org/wiki/Przeci%C4%85gnij_i_upu%C5%9B%C4%87">drag &amp; drop</a> i wyświetlał ich listę w postaci kontenerów. Po wykryciu, że internauta trzyma pliki nad przeglądarką nastąpi zachęcenie go do upuszczenia ich w odpowiednim miejscu poprzez podmianę napisu. Każdy kontener zaś będzie wyświetlał nazwę wybranego pliku, miniaturkę jeśli wybrany plik jest grafiką lub ewentualnie ikonkę zastępczą, pole tekstowe gdzie można dodać opis oraz przycisk wysyłania. Kontener będzie zawierał także przycisk usuwający dany plik z listy do wysłania oraz pole na wyświetlanie komunikatów. W momencie kliknięcia przycisku wysłania sam przycisk zniknie (aby użytkownik nie wysłał kilka razy tego samego pliku) i pojawi się w razie nie udanego uploadu. Każdorazowa próba wysłania spowoduje wyświetlenie odpowiedniego napisu w polu komunikatów. Jeśli chodzi o przesłane pliki to będą one zapisywane pod ustawionym adresem a opisy do nich będą lądować w pliku tekstowym o nazwie <em>&lt;nazwa pliku&gt;.txt</em>.</p>
<p><a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://example.mgdevelop.pl/uploadhtml5/">Wersja demonstracyjna skryptu (nie zapisuje plików na serwerze)</a></p>
<p>Gotowiec do pobrania na dole strony.</p>
<h1>Kod HTML</h1>
<p>Zacznijmy od napisania kodu tradycyjnego formularza:</p>
<pre class="brush:html">&lt;div id="uploadHTML"&gt;
    &lt;form enctype="multipart/form-data" action="uploadHtml.php" method="POST"&gt;
        &lt;input name="upload" type="file" /&gt;
        &lt;input value="Wyślij" type="submit" /&gt;
    &lt;/form&gt;
&lt;/div&gt;</pre>
<p>Ważne jest by objąć tą część kodu w blok z nadaną klasą <em>uploadHTML</em> gdyż później będziemy usuwać stary typ formularz poprzez odwołanie się do tej klasy. Podobny blok tworzymy dla naszego nowoczesnego uploadera:</p>
<pre class="brush:html">&lt;div id="uploadJS" style="display: none"&gt;
    //tu dalsza część kodu
&lt;/div&gt;</pre>
<p>Teraz wrzucamy do niego dwa elementy. Pole gdzie użytkownik ma upuścić plik:</p>
<pre class="brush:html">&lt;div class="uploader" id="uploader"&gt;
    Przenieś tu pliki które chcesz&lt;br /&gt;wysłać na serwer
&lt;/div&gt;</pre>
<p>oraz miejsce na listę plików do wysłania na serwer:</p>
<pre class="brush:html">&lt;div class="uploadList"&gt;
    //tu dalsza część kodu
&lt;/div&gt;</pre>
<p>Do tego diva wstawimy teraz przykładowy element a następnie go schowamy. Będzie to szablon dla skryptu jak mają wyglądać nowe elementy na liście.</p>
<pre class="brush:html">&lt;div id="uploadFileTemplate" class="uploadFile"&gt;
    &lt;div class="header"&gt;
        &lt;div class="name"&gt;Nazwa pliku.jpg&lt;/div&gt;
        &lt;div class="delete"&gt;×&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="thumb"&gt;
        &lt;img src="file.png" alt="Miniaturka" class="image" /&gt;
    &lt;/div&gt;
    &lt;div class="info"&gt;
        &lt;textarea name="description"&gt;&lt;/textarea&gt;
        &lt;p class="alert"&gt;&lt;/p&gt;
        &lt;input type="hidden" name="file" value=""&gt;
        &lt;div id="startUpload" class="submit"&gt;Wyślij plik&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>W powyższym nie trzeba raczej niczego tłumaczyć po za tym, że div z id <em>startUpload</em> będzie przyciskiem który rozpocznie upload a zaś plik file.png jest naszą domyślną ikonką. Aby szablon był niewidoczny dla użytkownika w arkuszu CSS piszemy:</p>
<pre class="brush:css">#uploadFileTemplate{
        display: none;
}</pre>
<h1>A teraz Javascript</h1>
<p>Po pierwsze dołączymy do naszego kodu bibliotekę <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://jquery.com/">jQuery</a> ponieważ dla łatwości pisania najlepiej będzie oprzeć nasz skrypt na tym frameworku.</p>
<pre class="brush:javascript">&lt;script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"&gt;&lt;/script&gt;</pre>
<p>Teraz zdefiniujemy parę zmiennym których użycie będę wyjaśniał później oraz napiszemy instrukcję która zapewni nam, że nasz kod nie wykona się za nim wszystkie elementy strony nie będą załadowane.</p>
<pre class="brush:javascript">var ePage;
var eDropPlace;
var eStartUpload;
var filesToUpload;
var newId;
var idi = 0;

$(document).ready(function(){
    //tu dalsza część kodu
});</pre>
<p>Wewnątrz tego kodu umieszczamy teraz instrukcję warunkową która wyświetli nasz uploader w przeglądarkah obsługujących wykorzystywane przez nas technologie:</p>
<pre class="brush:javascript">if (window.File &amp;&amp; window.FileReader &amp;&amp; window.FileList) {
    $("#uploadHTML").remove();
    $("#uploadJS").show();
    ePage               = document.getElementsByTagName('body').item(0);
    eDropPlace          = document.getElementById("uploader");
    //tu dalsza część kodu
}</pre>
<p>Powyższy kod działa w ten sposób, że sprawdzane jest czy przeglądarka obsługuje używane przez nas obiekty <em>File</em>, <em>FileReader</em> oraz <em>FileList</em>. Jeśli tak to usuwamy tradycyjny formularz a wyświetlamy ten nasz. Po tej operacji możemy już pobrać referencje do dwóch ważnych obiektów w naszym kodzie. <em>ePage</em> to cała nasza strona dla której będziemy wykrywali czy użytkownik przeniósł pliki nad okno przeglądarki. <em>eDropPlace</em> natomiast to miejsce gdzie użytkownik ma upuścić pliki. Mogłoby być to to samo miejsce ale w tym tutorialu zrobimy rozróżnienie aby lepiej wytłumaczyć czym to się różni.</p>
<h1>Zdarzenia ondragover i ondragleave</h1>
<p>Teraz poniżej tego (ale przed nawiasem klamrowym) dodamy obsługę zdarzeń. Po pierwsze obsłużmy przeniesienie plików nad przeglądarkę:</p>
<pre class="brush:javascript">ePage.ondragover=function(f){
    eDropPlace.innerHTML="Upuśc plik na to pole";
    f.dataTransfer.dropEffect="copy";
    f.preventDefault();
    return false
};</pre>
<p><em>ondragover</em> to właśnie zdarzenie polegające na tym, że użytkownik zaznaczył w folderze pliki i za pomocą myszki przeniósł je nad okno przeglądarki. Jeśli takie coś wykryjemy to zmieniamy treść napisu oraz zmieniamy kursor na informujący, że będziemy kopiować pliki (w Chrome np. przy kursorze pojawia się napis Kopiuj). Metoda<em>preventDefault()</em> natomiast zapewni nam, że przeglądarka nie zacznie się dziwnie zachowywać np. nie będzie zaznaczany tekst podczas przesuwania kursora nad oknem.</p>
<p>Podobne operacje wykonujemy dla zdarzenia przeciwnego czyli <em>ondragleave</em>:</p>
<pre class="brush:javascript">ePage.ondragleave=function(f){
    eDropPlace.innerHTML="Przenieś tu pliki które chcesz&lt;br /&gt;wysłać na serwer";
    f.dataTransfer.dropEffect="copy";
    f.preventDefault();
    return false
};</pre>
<p>Teraz czas na najważniejszą część kodu która obsłuży upuszczenie plików na okno przeglądarki (zdarzenie <em>ondrop</em>) i doda je do listy.</p>
<h1>Zdarzenie ondrop</h1>
<pre class="brush:javascript">ePage.ondrop=function(g){
    g.preventDefault();
    files = g.dataTransfer.files;
    eDropPlace.innerHTML ="Przenieś tu pliki które chcesz&lt;br /&gt;wysłać na serwer";

    //tu dalsza część kodu
}</pre>
<p>Ponownie skorzystaliśmy z metody <em>preventDefault()</em> gdyż przeglądarki domyślnie po upuszczeniu na nie pliku próbują je wyświetlać lub &#8222;ściągnąć&#8221;. Musimy temu zapobiec aby mógł się wykonać dalszy kod. Gdy to już mamy zapewnione to możemy skorzystać z instrukcji <em>g.dataTransfer.files</em> która zwróci nam tablicę obiektów poszczególnych plików. G zostało nam podane jako argument funkcji która wykona się w momencie zajścia zdarzenia <em>ondrop</em>. A jako, że internauta nie trzyma już plików to nie zajdzie zdarzenie <em>ondragleave</em> więc w powyższym kodzie obsługujemy przywrócenie napisu.</p>
<p>Teraz możemy już sobie iterować po tej tablicy i wyciągać kolejne obiekty plików do uploadu:</p>
<pre class="brush:javascript">for(var i = 0, f; f = files[i]; i++){
    var reader=new FileReader();

    //tu dalsza część kodu

    reader.readAsDataURL(f);
}</pre>
<p>Powyższa pętla przypisuje kolejne obiekty plików do zmiennej f, tworzy nowy obiekt klasy <em>FileReader</em> i wczytuje plik do stworzonego obiektu. I teraz naszym zadaniem jest napisanie funkcji która zostanie wykonana gdy cały plik zostanie wczytany (jest on wczytywany asynchronicznie z powodu opóźnienia jakie może wywołać obciążony dysk twardy). Wykonuje się to za pomocą nietypowej konstrukcji która należy umieścić przed użyciem metody <em>readAsDataURL</em>:</p>
<pre class="brush:javascript">reader.onload = (function(theFile) {
    return function(e) {
        //tu dalsza część kodu
    };
})(f);</pre>
<p>Jakkolwiek dziwnie powyższy kod wygląda to nadszedł czas na napisanie funkcji tworzącego nowe elementy na liście. Na początek musimy przyjąć, że każdemu nowemu kontenerowi będziemy nadawać ID wg schematu: <em>file1</em>, <em>file2</em>, <em>file3</em> itd. Realizuje to poniższy kod:</p>
<pre class="brush:javascript">var newId = "file"+idi; idi++;
$(".uploadList").prepend("&lt;div id=\""+newId+"\" class=\"uploadFile\"&gt;"+$("#uploadFileTemplate").html()+"&lt;/div&gt;");</pre>
<p>Jak widać stworzyliśmy nowy kontener, nadaliśmy mu id i skopiowaliśmy do niego nasz szablon z diva <em>uploadFileTemplate</em>. Nowy element pojawi się na liście plików na samej górze dzięki metodzie <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://api.jquery.com/prepend/">prepend</a> z biblioteki jQuery.</p>
<p>Teraz czas na wypełnienie naszego szablonu i nadaniu zdarzeń dla przycisków:</p>
<pre class="brush:javascript">$("#"+newId+" .header .name").text(theFile.name);

//wrzuca miniatirku zdjęć
if(theFile.type.match(/image.*/))
    $("#"+newId+" .thumb .image").attr("src",e.target.result);</pre>
<p>Obiekt theFile w tym momencie przechowuje informacje i naszym pliku. Pobieramy z niego nazwę pliku (<em>theFile.name</em>) i wpisujemy w odpowiednim miejscu. Dalej sprawdzamy czy nasz plik jest obrazkiem za pomocą <em>theFile.type.match(/image.*/)</em>. Jeśli tak to odczytujemy nasz plik z zmiennej <em>e.target.result</em> i wpisujemy jako atrybut<em>src</em> miniaturki. Plik jest przechowywany w wspomnianej zmiennej w formacie <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://pl.wikipedia.org/wiki/Base64">base64</a>. Polecam kliknąć na tak wyświetloną grafikę PPM i wybrać opcję <em>Pokaż obrazek</em>. Zobaczymy wtedy w pasku adresu jak wygląda grafika w takim kodowaniu.</p>
<pre class="brush:javascript">//zapisuje plik do pola tekstowego
$("#"+newId+" input[name=\"file\"]").val(e.target.result.split(",")[1]);

//obsługa usuwania pliku
$("#"+newId+" .delete").click(function(z){
    $("#"+newId).remove();
});

//obsługa wysyłania
$("#"+newId+" #startUpload").click(function(z){
    trySendFile(newId);
});</pre>
<p>Wracając do naszego szablonu to teraz znowu musimy odczytać nasz plik i zapisać go do pola tekstowego o nazwie <em>file</em>. Teraz jednak przypiszemy tylko sam kod bez informacji o typie kodowania. Przy użyciu javascriptowej metody <a title="Zewnętrzny odnośnik" rel="nofollow external" href="https://developer.mozilla.org/en/Javascript/Reference/Global_Objects/String/split">split</a> wytniemy zbędny w tym przypadku napis <em>data:image/png;base64,</em>. W dalszej części kodu oskryptowujemy przycisk anulowania wysyłania pliku którego kliknięcie spowoduje usunięcie całego kontenera oraz przycisk wysyłania pliku którego kliknięcie wywoła większą funkcję <em>trySendFile</em>.</p>
<p>I to wszystko jeśli chodzi o obsługę zdarzenia <em>ondrop</em>. Czy czegoś nam brakuje? Tak, definicji funkcji&#8230;</p>
<h1>trySendFile</h1>
<pre class="brush:javascript">function trySendFile(eId){
    $("#"+eId+" #startUpload").hide();

    var fileData = $("#"+eId+" input[name=\"file\"]").val();
    fileData = fileData.replace(/\+/gi, '-');
    fileData = fileData.replace(/\//gi, '_');

    //dalsza część kodu
}</pre>
<p>Po kliknięciu przycisku wysyłania pierwsze co musi się stać to schowanie owego guzika. Następnie z pola tekstowego <em>file</em> odczytujemy zakodowany plik i podmieniamy w nim pewne znaki. Ktoś może zapytać po co? Po odpowiedź odprowadzam do <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://pl.wikipedia.org/wiki/Base64">artykułu o base64 na Wikipedii</a> a dokładniej to do akapitu pod tabelką. My będziemy transportować plik w ciągu <em>zmienna1=wartosc1&amp;zmienna1=wartosc2&#8230;</em> więc musimy zadbać by żadne znaki nam nie uszkodziły danych. Dwie linijki z powyższego kodu realizują właśnie podmianę omówioną na Wikipedii.</p>
<p>Teraz możemy w końcu znapisać kod które wyśle wszystkie dane na serwer (np do <em>pliku php/getFile.php</em>):</p>
<pre class="brush:javascript">$.ajax({
    type: "POST",
    url: "php/getFile.php",
    data:   "file="+fileData+
            "&amp;name="+encodeURIComponent($("#"+eId+" .header .name").html())+
            "&amp;description="+encodeURIComponent($("#"+eId+" textarea[name=\"description\"]").val()),
    //tu za chwilę dalszy ciąg kodu
});</pre>
<p>Jak widać używamy tu funkcji <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://api.jquery.com/jQuery.ajax/">ajax</a> z biblioteki jQuery. Jako parametr <em>data</em> podajemy ciąg gdzie kolejno składamy zmienne <em>file</em> zawierającą kod base64, <em>name</em> zawierającą nazwę pliku oraz <em>description</em> zawierającą treść z pola tekstowego. Wartości pól <em>name</em> i <em>description</em> zabezpieczyliśmy funkcją <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://www.w3schools.com/jsref/jsref_encodeURIComponent.asp">encodeURIComponent</a> aby dało się je bezpiecznie przesłać w tej formie. I tu znowu ktoś może zapytać dlaczego nie użyliśmy tej metody wcześniej przy zabezpieczaniu base64. Powód jest prosty. Wspomniana metoda podmienia wszystkie znaki specjalne. Jeśli plik waży kilka megabajtów (np. plik <em>.mp3</em>) to użycie omawianej metody powoduje chwilowe zawieszenie przeglądarki. A, że na szczęście w base64 występują tylko dwa <em>psujaki</em> to o wiele optymalnej jest użyć podmiany metodą <em>replace</em>.</p>
<p>Dane zostały wysłane więc teraz trzeba by było obsłużyć odpowiedź. Za nim to jednak zrobimy napiszmy:</p>
<h1>Kod po stronie serwera</h1>
<p>Tu nie będziemy się rozpisywać. Nie podam tu jakiegoś bardzo użytecznego kodu a tylko skrypt który pozwoli przetestować nam uploader i zrozumieć jak należy odbierać kod base64.</p>
<pre class="brush:php">&lt;?php
    $name = str_replace('..',' ',$_POST['name']);
    $name = str_replace('/',' ',$_POST['name']);
    $name = str_replace('.exe',' ',$name);

    if(!file_exists("files/".$name)){
        //dalszy kod
    } else echo "error!Taki plik już istnieje";
?&gt;</pre>
<p>Jak widać w pliku getFile.php najpierw usuwamy z nazwy pliku podwójne kropki i ukośniki aby zapobiec, że jakiś spryciarz zapisze nam plik po za naszym folderem. Usuwamy także rozszerzenia z plików wykonywalnych dla bezpieczeństwa serwera i osoby która będzie te pliki przeglądać. Gdy to już zrobimy sprawdzamy czy nie ma takiego pliku w folderze do uploadu. Jeśli nie to wykonujemy dalszy kod, w przeciwnym wypadku zwracamy przeglądarce komunikat o błędzie. Komunikaty będziemy zwracać w formacie <em>&lt;typ komunikatu&gt;!&lt;treść komunikatu&gt;</em>. Wspomniany dalszy kod wygląda następująco:</p>
<pre class="brush:php">$file = str_replace('-','+',$_POST['file']);
$file = str_replace('_','/',$file);
$f = fopen("files/".$name, "wb");
fwrite($f, base64_decode($file));
fclose($f);
$f = fopen("files/".$name.".txt", "wb");
fwrite($f, $_POST['description']);
fclose($f);
echo "ok!Plik zapisano";</pre>
<p>Po pierwsze przywracamy podmienione wcześniej znaki. Po drugie otwieramy plik o odpowiedniej nazwie i zapisujemy do niego odkodowaną za pomocą <a title="Zewnętrzny odnośnik" rel="nofollow external" href="http://www.php.net/manual/en/function.base64-decode.php">base64_decode</a>treść pliku. Po trzecie zaś otwieramy plik o nazwie <em>&lt;nazwa pliku uploadowanego&gt;.txt</em> i wrzucamy do niego opis napisany przez internautę. Po czwarte zwracamy komunikat, że wszystko poczło dobrze i po piąte&#8230;</p>
<h1>Piszemy ostatni fragment kodu JS</h1>
<p>Teraz wracamy do naszej niedokończonej funkcji ajaxowej i dopisujemy odbiór komunikatów:</p>
<pre class="brush:javascript">    error: function(xhr, ajaxOptions, thrownError){
            $("#"+eId+" p.alert").text("Błąd połęczenia");
            $("#"+eId+" #startUpload").show();
        },
    success: function(msg){
            $("#"+eId+" #startUpload").show();
            var data = msg.split("!");
            switch(data[0]){
                case "error":    $("#"+eId+" p.alert").text(data[1]);
                                 break
                case "ok":       $("#"+eId+" p.alert").text(data[1]);
                                 $("#"+eId+" #startUpload").remove();
                                 break;
                default:         alert(msg);
                                 break;        
            }
        }</pre>
<p>Funkcja napisana po parametrze <em>error</em> jest wykonywana gdy przeglądarka nie może połączyć się z serwerem lub znaleźć pliku. W takim przypadku wyświetlamy internaucie napis, że <em>Brak połączenia</em> i przywracamy przycisk by mógł spróbować raz jeszcze. Zaś <em>success</em> odnosi się do przypadku gdy serwer zwrócił nam jakąś sensowną odpowiedź. Wtedy także przywracamy przycisk a odpowiedź z serwera (zmienna msg) rozwalamy na dwie części znaną już metodą split. Potem sprawdzamy czy komunikat jest typu error czy ok i wykonujemy odpowiednie operacje: wyświetlamy treść komunikatu i ewentualnie kasujemy przycisk wysyłania jak wszystko poszło ok. Gdyby zaś nie udało nam się rozpoznać typu komunikatu (np. zwrócono nam błąd php) to wyświetlamy całość za pomocć alertu</p>
<h1>Gotowiec</h1>
<p>Wszystkie pliki potrzebne do uruchomienia stworzone uploadera można pobrać <a title="Uploader w HTML5" href="http://example.mgdevelop.pl/uploadhtml5/uploader.zip">stąd</a>.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2011/06/uploader-plikow-z-wykorzystaniem-html5/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Rozmowa z wujkiem Marcinem cz.2</title>
		<link>http://mgdevelop.pl/index.php/2010/08/rozmowa-z-wujkiem-marcinem-cz-2/</link>
		<comments>http://mgdevelop.pl/index.php/2010/08/rozmowa-z-wujkiem-marcinem-cz-2/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 09:46:11 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[HTML i CSS]]></category>
		<category><![CDATA[frame]]></category>
		<category><![CDATA[iframe]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[standardy]]></category>
		<category><![CDATA[W3C]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=488</guid>
		<description><![CDATA[O, to znowu Ty, mój początkujący miłośniku tworzenia stron internetowych. Pewnie znowu przyszedłeś o coś zapytać. Nie ma problemu. Wejdź... <a href="http://mgdevelop.pl/index.php/2010/08/rozmowa-z-wujkiem-marcinem-cz-2/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>O, to znowu Ty, mój początkujący miłośniku tworzenia stron internetowych. Pewnie znowu przyszedłeś o coś zapytać. Nie ma problemu. Wejdź i usiądź. Opowiedz z czym masz problem. Zaparzyć Ci herbaty?<span id="more-488"></span></p>
<p><strong>Nie, dziękuję. Chodzi to, że niedawno przerzuciłem się z tabelek na divy bo wszyscy mówią, że to jest lepsze. Ale ostatnio zaglądałem do kodu phpBB3 i tam wszystko stoi na tabelkach. Wydawało mi się, że twórcy tego skryptu znają się na swojej pracy a jednak korzystają z starych rozwiązań. To jak to w końcu jest? Co jest lepsze? Tabelki czy divy?</strong></p>
<p>Obydwa rozwiązania są dobre w zależności do czego je używasz. Mówiąc krótko divy powinny być używane do budowy kontrukcji wyglądu strony. Na przykład umieszczenia loga na górze, sidebara z boku i stopki na dole. Tabelki zaś należy stosować tylko gdy chcemy wyświetlić jakieś dane tabelaryczne. Podchodzą pod to między innymi dane statystyczne oraz wielokolumnowe listy jak na np. interfejsy na forach. Tabelek nie powinno zaś się używać gdy chcemy dla przykładu stworzyć trzy kolumnową stronę i w tym celu tworzyć tabeli z trzema kolumnami. Takie rozwiązanie to nieporozumienie gdyż zwiększa czas jaki przeglądarki potrzebują do wyświetlenia witryny. Da się zauważyć to opóźnienie gdy np. środkowa kolumna zawiera dużo grafik. Wtedy na wyświetlenie komórki po prawej możemy musieć trochę poczekać.</p>
<p><strong>Ok. A jak wygląda sprawa z ramkami?</strong></p>
<p>Zwykłe ramki wyszły już całkiem z użycia. Chodzi mi tu o elementy <em>frame</em> i <em>frameset</em>. Nie powinno się ich używać gdyż obecnie istnieją o wiele lepsze rozwiązania jak na przykład php lub ajax. Co zaś się tyczy ramek pływających, to znaczy elementów <em>iframe</em> to są one wciąż w użyciu ale radzi się ich już wystrzegać. Inaczej mówiąc skorzystanie z nich to nic złego ale jeśli tylko jest możliwość to powinno skorzystać się z innej techniki.</p>
<p><strong>Ciekawe. A są jeszcze jakieś nowe standardy o których powinien wiedzieć każdy początkujący?</strong></p>
<p>Długo by tu wymieniać ale pokrótce mogę wymienić parę punktów. Po pierwsze aktualnie jedyne kodowanie znaków jakiego powinno się używać to UTF-8. I od tego nie ma odstępstw. Używając tego kodowania pozbędziesz się problemów na stronach wielojęzykowych oraz przy korzystaniu z zewnętrznych interfejsów np. przycisków Facebooka. Ponadto wycofano wszystkie dziwne znaczniki typu <em>&lt;font&gt;</em>, <em>&lt;big&gt;</em> itd dotyczących wyglądu tekstu. Zamiast nich należy stosować znacznika <em>&lt;span&gt;</em> i odpowiednie style CSS. Nawet zamiast <em>&lt;b&gt;</em> radzi się korzystać z <em>&lt;strong&gt;</em> chociaż ten pierwszy wciąż oficjalnie jest w użyciu.</p>
<p><strong>Dobrze, przestańmy już mówić o tym htmlu. Ostatnio chciałem poszerzyć swoje horyzonty i pouczyć się JavaScriptu. Ale mam mały dylemat. Czego radzisz się uczyć? JavaScriptu czy może tej słynnej biblioteki jQuery.</strong></p>
<p>Na początek może wyjaśnię, że jQuery to zestaw funkcji napisanych w języku  JavaScript. Ale jeśli dopiero zaczynasz swoją przygodę z językami skryptowymi to radzę ci zacząć uczyć się samego JS. Dlaczego? Ponieważ umiejąc korzystać z jQ ale nie znając dobrze niektórych możliwości JavaScriptu będziesz mocno ograniczony. Mam tu na myśli wszystkie funkcję odpowiedzialne za przetwarzanie tekstu, dokonywanie obliczeń czy obsługę zdarzeń. Gdy to już opanujesz możesz śmiało ruszać do nauki JQuery. Pisanie skryptów stanie się dla Ciebie o wiele łatwiejsze i ponadto będziesz miał wiedzę potrzebną do pisania zaawansowanych aplikacji internetowych.</p>
<p><strong>A istnieją jakieś alternatywy do jQuery?</strong></p>
<p>Tak, np. Prototype i Moo Tools. Te biblioteki są jednak mniej popularne od jQuery i możesz przy nich liczyć na mniejsze wsparcie społeczności.</p>
<p><strong>Dobrze wiedzieć. Ok, to chyba dziś już na tyle.</strong></p>
<p>W porządku. Wracaj jak tylko nazbierają Ci się znowu jakieś problemy.</p>
<p><strong>Na pewno przyjdę Cię pomęczyć, cześć.</strong></p>
<p>Trzymaj się.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/08/rozmowa-z-wujkiem-marcinem-cz-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Zaokrąglony przycisk o nieustalonej szerokości</title>
		<link>http://mgdevelop.pl/index.php/2010/08/zaokraglony-przycisk-o-nieustalonej-szerokosci/</link>
		<comments>http://mgdevelop.pl/index.php/2010/08/zaokraglony-przycisk-o-nieustalonej-szerokosci/#comments</comments>
		<pubDate>Mon, 02 Aug 2010 15:23:57 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[HTML i CSS]]></category>
		<category><![CDATA[background]]></category>
		<category><![CDATA[cięcie]]></category>
		<category><![CDATA[przycisk]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=472</guid>
		<description><![CDATA[W tym poradniku postaram się wyjaśnić jak koduje się obrazkowe przyciski z zaokrąglonymi rogami jeśli nie wiemy ile będzie w... <a href="http://mgdevelop.pl/index.php/2010/08/zaokraglony-przycisk-o-nieustalonej-szerokosci/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>W tym poradniku postaram się wyjaśnić jak koduje się obrazkowe przyciski z zaokrąglonymi rogami jeśli nie wiemy ile będzie w nich tekstu, a co za tym idzie nie ma on konkretnej szerokości. Taki przypadek może się zdarzyć np. przy budowie CMSa gdzie nie możemy przewidzieć jakie napisy umieści użytkownik w menu.</p>
<h1><span id="more-472"></span> Grafika</h1>
<p>Finalnie nasza praca ma wyglądać tak:</p>
<p><a href="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/button.png"><img class="alignnone size-full wp-image-475" title="button" src="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/button.png" alt="" width="200" height="30" /></a></p>
<p>Jak widać przy większej ilości tekstu grafika musi się się rozszerzać. Aby tak było trzeba to sprytnie zakodować. Najpierw jednak musimy przygotować dwie grafiki. Jedną która będzie się składała tylko z prawych zaokrągleń i druga która będzie bardzo szeroką wersją buttonu ale bez zaokrągleń po prawej. Dokładniej to potrzebujemy takich obrazków:</p>
<p><a href="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/right.png"><img class="alignnone size-full wp-image-477" title="right" src="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/right.png" alt="" width="22" height="30" /></a></p>
<p><a href="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/right.png"></a><a href="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/left.png"><img class="alignnone size-full wp-image-476" title="left" src="http://mgdevelop.pl/mgdevelop/wp-content/uploads/2010/08/left.png" alt="" width="500" height="30" /></a></p>
<p>Ważne jest to aby obrazki miały jednolite lub prawie jednolite tło. W tym przypadku jest ono białe.</p>
<h1>Kod</h1>
<p>Przy kodowaniu użyjemy pewnej sztuczki. Krótszy obrazek wstawimy jako tło linku przycisku a sam link wstawimy do diva któremu jako tło nadamy dłuższy obrazek. Dzięki temu krótsza grafika odpowiednio zasłoni tą dłuższą. Oto kod html:</p>
<pre class="brush: html">&lt;div class="przycisk"&gt;&lt;a href="#"&gt;Przejdź do galerii zdjęć&lt;/a&gt;&lt;/div&gt;</pre>
<p>A poniżej kod CSS:</p>
<pre class="brush: css"> .przycisk{
    height: 30px;
    background: url('left.png') no-repeat;
    display: block;
    float: left;
 }
 .przycisk a{
    height: 30px;
    background: url('right.png') right no-repeat;
    display: block;
    padding: 0 15px 0 15px;
    font: italic normal bolder 14px Georgia;
    text-decoration: none;
    color: #dadada;
    line-height: 30px;
 }</pre>
<p>Jak widać obrazek <em>right.png</em> dosunęliśmy do prawej strony aby pojawił się w odpowiednim miejscu. Musieliśmy także użyć <em>float: left</em> aby wszystko przyjmowało możliwie najmniejszą szerokość. Kod w działaniu można zobaczyć <a title="zaokrąglony przycisk" href="http://example.mgdevelop.pl/zaokraglonyprzycisk/">pod tym linkiem</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/08/zaokraglony-przycisk-o-nieustalonej-szerokosci/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Sortowalne elementy z zapisem kolejności</title>
		<link>http://mgdevelop.pl/index.php/2010/07/sortowalne-elementy-z-zapisem-kolejnosci/</link>
		<comments>http://mgdevelop.pl/index.php/2010/07/sortowalne-elementy-z-zapisem-kolejnosci/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 22:36:09 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[sortable]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=354</guid>
		<description><![CDATA[Wyobraźmy sobie sytuację, że mamy na swojej stronie kilka rubryczek ustawione w jednym rzędzie i w każdej jest zawartość która... <a href="http://mgdevelop.pl/index.php/2010/07/sortowalne-elementy-z-zapisem-kolejnosci/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Wyobraźmy sobie sytuację, że mamy na swojej stronie kilka rubryczek ustawione w jednym rzędzie i w każdej jest zawartość która zainteresuje inne osoby np: sidebar z listami ostatnich wpisów osobno dla różnych kategorii. I teraz możemy mieć dylemat którą tematykę dać na górę a którą ukryć niżej. Jest jednak rozwiązanie: możemy pozwolić użytkownikom aby sami ustalali kolejność która później będzie przywracana przy każdym wczytaniu strony.<span id="more-354"></span></p>
<h1>jQuery i wtyczki</h1>
<p>Pisanie skryptu zaczynamy od pobrania jQuery i dołączenia do swojego kod, tak samo musimy zrobić z jQuery UI gdyż tam znajduję się plugin Sortable na którym oprzemy nasz skrypt. Gdy już to mamy możemy napisać kod html:</p>
<pre class="brush: html">&lt;div class="box"&gt;
   &lt;div id="m" class="element"&gt;matematyka&lt;/div&gt;
   &lt;div id="f" class="element"&gt;fizyka&lt;/div&gt;
   &lt;div id="c" class="element"&gt;chemia&lt;/div&gt;
   &lt;div id="i" class="element"&gt;informatyka&lt;/div&gt;
   &lt;div id="e" class="element"&gt;ekonomia&lt;/div&gt;
&lt;/div&gt;</pre>
<p>Box to nasz pojemnik z divami które będziemy sortować. Każdy z tych elementów musi mieć inne ID by skrypt mógł je rozpoznawać. Poniżej zaś kod JavaScript który uruchomi sortowanie:</p>
<pre class="brush: javascript">$(".box").sortable({ items: '.element' });</pre>
<p>W tym momencie będzie już działać sortowanie ale po odświeżeniu wszystkie elementy wrócą na swoje miejsce. Aby móc zapisać kolejność będziemy musieli skorzystać z mechanizmu ciastek. Aby ułatwić sobie ich obsługę skorzystamy z dwóch specjalnych funkcji które można skopiować <a title="Funkcje do obsługi ciasteczek" href="http://example.mgdevelop.pl/sortowanieizapis/ciasteczka.js">stąd</a>. Przyda się również wtyczka w jQuery do sortowania elementów DOM. Użyjemy qsort którą można pobrać <a title="pobieranie wtyczki Qsort" href="http://plugins.jquery.com/project/qsort">tutaj</a>. Gdy już wszystko podepniemy do naszej strony możemy zacząć pisać nasz skrypt.</p>
<h1>Szczypta naszego kodu</h1>
<p>Najpierw napiszemy kod do zapisywania kolejności. Aby to zrobić musimy do wcześniej napisanego wywołania funkcji sortable dopisać parę dodatkowych linijek.</p>
<pre class="brush: javascript">$(".box").sortable({
   items: '.element',
   update: function(event, ui){
      var k = $(".box").sortable("toArray");
      var ks = k.toString();
      SetCookie('kolejnosc', ks, 30);
   }
});</pre>
<p>Skorzystaliśmy tu z zdarzenia update które jest wywoływane zawsze gdy zmieniona zostanie kolejność elementów. Podpięta funkcja anonimowa najpierw uruchamia metodę <em>toArray</em> by wtyczka sortable zwróciła tablicę id kolejnych elementów, następnie otrzymana tablica jest serializowana by na końcu otrzymany ciąg został zapisany do ciasteczka.</p>
<p>Teraz pozostał nam jeszcze do napisania skrypt który po wczytaniu strony będzie ustawiał elementy w odpowiedniej kolejności. Oto i on:</p>
<pre class="brush: javascript">if(GetCookie('kolejnosc')){
   var kol = GetCookie('kolejnosc').split(',');
   for(var j=0;j&lt;kol.length;j++){
      $('#'+kol[j]).attr('value',j);
   }
   $('.element').qsort({attr: "value"});
   SetCookie('kolejnosc', kol, 30);
}</pre>
<p>Powyższą instrukcję należy wywołać gdy cała strona jest już załadowana. Skrypt działa następująco: najpierw sprawdzamy czy istnieje ciasteczko, jeśli tak to wyciągamy z niego informacje i deserializujemy je do tablicy. Następnie w pętli kolejnym sortowalnym elementom nadajemy value o wartości takiej jaką powinno zajmować miejsce. Gdy to już mamy zrobione uruchamiamy funkcję qsort i na końcu przedłużamy żywotność ciasteczka.</p>
<p>Cały skrypt  z dokładnymi komentarzami można skopiować <a title="NCały napisany przez nas kod" href="http://example.mgdevelop.pl/sortowanieizapis/naszkod.js">tutaj</a> a strona z gotowym efektem jest do zobaczenia w<a title="Gotowy efekt" href="http://example.mgdevelop.pl/sortowanieizapis/"> tym miejscu</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/07/sortowalne-elementy-z-zapisem-kolejnosci/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Obsługa protokołu GG w PHP</title>
		<link>http://mgdevelop.pl/index.php/2010/07/obsluga-protokolu-gg-w-php/</link>
		<comments>http://mgdevelop.pl/index.php/2010/07/obsluga-protokolu-gg-w-php/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 22:31:45 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[PHP & MySQL]]></category>
		<category><![CDATA[Gadu-Gadu]]></category>
		<category><![CDATA[komunikator]]></category>
		<category><![CDATA[protokół]]></category>
		<category><![CDATA[wiadomości]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=278</guid>
		<description><![CDATA[Witam w poradniku z którego będzie można się dowiedzieć w jaki sposób można wysyłać wiadomości z poziomu PHP do najpopularniejszej... <a href="http://mgdevelop.pl/index.php/2010/07/obsluga-protokolu-gg-w-php/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Witam w poradniku z którego będzie można się dowiedzieć w jaki sposób można wysyłać wiadomości z poziomu PHP do najpopularniejszej w Polsce sieci komunikatorów, sieci Gadu-Gadu. Ta wiedza da nam możliwość tworzenia szybkich i skutecznych systemów powiadamiania internautów o nowych postach czy wydarzeniach na naszych stronach internetowych. Zaczynamy!<br />
<span id="more-278"></span></p>
<h1>Początek przygody</h1>
<p>Aby zacząć pisać skrypt do wysyłania wiadomości na GG musimy wpierw pobrać mały plik z klasą do obsługi protokołu. Jest  on do pobrania <a title="Klasa do obslugi protokolu gadu-gadu" href="http://lgpl.nastal.pl/rfGG.class.zip">tutaj</a>. Wypakowywujemy go, dołączamy do naszego skryptu a także tworzymy obiekt tej klasy:</p>
<pre class="brush: php">require_once('rfGG.class.php');
$GG = new rfGG(rfGG::VER_77);</pre>
<p>Teraz musimy używając aplikacji GG lub innego zgodnego komunikatora np AQQ utworzyć konto dla naszego bota który będzie rozsyłał wiadomości. Nie możemy używać naszego konta. Gdy już mamy nowy numer i hasło możemy przystąpić do próby nawiązania połączenia z serwerem GG.</p>
<pre class="brush: php">if ($GG-&gt;connect('123456789','hasłobota')) {
   $GG-&gt;disconnect();
}</pre>
<div>Działanie powyższego kodu jest krótkie, łączy się on z serwerem za pomocą podanych informacji a następnie jeśli wszystko pójdzie pomyślnie rozłącza się zmieniając status na niedostępny.</div>
<h1>Zmiana statusu i opisu</h1>
<p>Klasa rfGG posiada funkcję changeStatus() która służy do zmiany statusu oraz opisu konta bota.</p>
<pre class="brush: php">if ($GG-&gt;connect('123456789','hasłobota')) {
   $GG-&gt;changeStatus(rfGG::STATUS_BUSY_DESCR,'Code is poetry');
   //tutaj jakiś kod...
   $GG-&gt;disconnect('nie ma mnie');
}</pre>
<p>W tym przykładzie ustawiliśmy status na STATUS_BUSY_DESCR a opis na <em>Code is poetry</em>. Poniżej zamieszczam listę wszystkich statusów oraz ich znaczeń.</p>
<ul>
<li>STATUS_NOT_AVAIL &#8211; niedostępny</li>
<li>STATUS_NOT_AVIAL_DESCR &#8211; niedostępny z opisem</li>
<li>STATUS_AVAILABLE<span style="white-space: pre;"> </span>- dostępny</li>
<li>STATUS_AVAILABLE_DESCR &#8211; dostępny z opisem</li>
<li>STATUS_BUSY<span style="white-space: pre;"> </span>- zajęty (zaraz wracam)</li>
<li>STATUS_BUSY_DESCR<span style="white-space: pre;"> </span> &#8211; zajęty z opisem</li>
<li>STATUS_INVISIBLE &#8211; niewidoczny</li>
<li>STATUS_INVISIBLE_DESCR &#8211; niewidoczny z opisem</li>
</ul>
<p>Przy statusach z opisem trzeba jako drugi argument funkcji podać tekst który będzie wyświetlany jako opis. Funkcja <em>disconnect()</em> służąca do rozłączania z serwerem automatycznie zmienia status na niedostępny i ewentualnie ustawia przekazany jej argument jako opis. W powyższym przykładzie skorzystaliśmy z tej możliwości i ustawiliśmy opis na <em>nie ma mnie</em>.</p>
<h1>Wysyłanie wiadomości</h1>
<p>Proszę zapiąć pasy ponieważ przechodzimy do ważnej części poradnika. Zajmijmy się teraz wysyłaniem wiadomości. Gdy już jesteśmy zalogowani w serwerze GG możemy to zrobić za pomocą odpowiedniej funkcji:</p>
<pre class="brush: php">if ($GG-&gt;connect('123456789','hasłobota')) {
   $GG-&gt;sendMessage('300500800',"Treść &lt;b&gt;wiadomości&lt;/b&gt;...");
   $GG-&gt;disconnect();
}</pre>
<p>Funkcja ta to <em>sendMessage()</em> i przyjmuje dwa argumenty, numer odbiorcy oraz treść wysyłanej wiadomości. Jak widać w przykładzie wiadomość może zawierać tagi HTML. Dopuszczone są pogrubienia &lt;b&gt;, pochylenia &lt;i&gt;, podkreślenia &lt;u&gt; oraz złamanie linii za pomocą &lt;br&gt; lub \r\n. Funkcja po próbie wysłania wiadomość zwraca true lub false w zależności czy wszystko się udało. Można to wykorzystać do sprawdzenia powodzenia wysłania komunikatu i ewentualnie wyświetlić błąd przy użyciu <em>getError()</em>.</p>
<pre class="brush: php">if (!$GG-&gt;sendMessage($numer,$tresc)) {
   die($GG-&gt;getError());
}</pre>
<h1>Odbieranie wiadomości</h1>
<p>Używana przez nas klasa zezwala również na odbieranie wiadomości. Robi się to za pomocą dwóch funkcji:  <em>getMessages()</em> i <em>getMessageOne()</em>. Najpierw omówimy tą pierwszą gdyż jest bardziej uniwersalna.</p>
<pre class="brush: php">require_once('rfGG.class.php');
$GG = new rfGG(rfGG::VER_77);
if ($GG-&gt;connect('222333444','password')) {
   $GG-&gt;ping();
   $message = $GG-&gt;getMessages();
   for($i=0;$i&lt;count($message);$i++){
      echo $message[$i]['sender'].'&gt;'.$message[$i]['msg_text'].'&lt;br&gt;';
   }
   $GG-&gt;disconnect('Code is poetry');
}</pre>
<p>Jak widać w powyższym kodzie przez przetworzeniem wiadomości wywołaliśmy funkcję <em>ping()</em> która ma za zadanie nawiązać kontakt z serwerem i pobrać czekające na nas dane. Należy tej funkcji używać zawsze przed funkcjami do wyświetlania wiadomości. Później możemy z otrzymaną tablicą wiadomości zrobić co chcemy. W tym przykładzie wyświetlamy numer z którego otrzymano informację oraz jej treść. Zwracana tablica ma zawsze ten sam schemat. Pierwszy jej wymiar to liczba porządkowa kolejnych wiadomości a drugi to elementy o indeksach sender (numer nadawcy), time (czas w formacie timestamp), msg_text (treść) i 2 inne, nie istotne dla nas.</p>
<p>Funkcja <em>getMessageOne()</em> działa podobnie tylko, że zwraca jedną wiadomość. Trzeba więc ją wykonywać wielokrotnie. Zwraca ona tablicę jednowymiarową z elementami o indeksach takich samych jak drugi wymiar poprzedniej funkcji.</p>
<h1>Pewne zasady</h1>
<p>Na koniec chciałbym zacytować fragment licencji z pliku używanej przez nas klasy:</p>
<ul>
<li><em>4. Kategorycznie zabrania sie wykorzystywania kodu do rozsylania SPAMU oraz niechcianych wiadomosci.</em></li>
<li><em>5. Odbiorca wiadomosci musi wyrazic wczesniej zgode na ich otrzymywanie.</em></li>
<li><em>6. Zabrania sie wykorzystywania kodu do celow niezgodnych z prawem POLSKIM.</em></li>
<li><em>7. Na uzasadniona prosbe serwisu Gadu-Gadu nalezy usunac lub wylaczyc działanie kodu.</em></li>
</ul>
<p>I ja również podpisuje się pod tym ponieważ nikt z nas przecież nie chce otrzymywać spamu na komunikator, prawda?</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/07/obsluga-protokolu-gg-w-php/feed/</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>Rozmowa z wujkiem Marcinem cz1</title>
		<link>http://mgdevelop.pl/index.php/2010/07/rozmowa-z-wujkiem-marcinem-cz1/</link>
		<comments>http://mgdevelop.pl/index.php/2010/07/rozmowa-z-wujkiem-marcinem-cz1/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 18:38:02 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[HTML i CSS]]></category>
		<category><![CDATA[div]]></category>
		<category><![CDATA[float]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[position]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=317</guid>
		<description><![CDATA[Witaj! Jesteś początkującym webmasterem? I jeszcze nie ogarniasz tego wszystkiego i co chwilę masz problemy? Spokojnie, wejdź, usiądź, po prostu... <a href="http://mgdevelop.pl/index.php/2010/07/rozmowa-z-wujkiem-marcinem-cz1/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Witaj! Jesteś początkującym webmasterem? I jeszcze nie ogarniasz tego wszystkiego i co chwilę masz problemy? Spokojnie, wejdź, usiądź, po prostu się rozgość. Zaraz spróbujemy Ci pomóc. Herbaty? Nie? To sam się napiję&#8230;a więc z czym przychodzisz? Jakie masz problemy? Szybko, pytaj!<span id="more-317"></span><strong> </strong></p>
<p><strong>Eee&#8230; ostatnio przerzuciłem się z tabel na divy i mam kłopot. Nie wiem jak wyśrodkować diva. Wiesz jak to zrobić?</strong></p>
<p>Oczywiście. Wystarczy mu nadać stałą szerokość oraz <em>margin: auto</em>. Nic trudnego.</p>
<p><strong>No dobrze, a w takim razie w jaki sposób ustawić dwa divy obok siebie? Żeby utworzyły się dwie kolumny. </strong></p>
<p>Ponownie musisz obu blokom ustawić stałą szerokość a ponadto każdemu nadać  <em>float: left</em>. Ewentualnie obu <em>float: right</em> lub też jednemu <em>float: left</em> a temu drugiemu <em>float: right</em>. Jeśli tylko suma szerokości tych bloków będzie wystarczająco mała aby zmieściły się obok siebie to wszystko powinno działać tak jak chcesz.</p>
<p><strong>Kiedyś tak próbowałem ale mimo, że rozmiary się zgadzały to jednak te dwa bloki nie mieściły się obok siebie!</strong></p>
<p>Pamiętaj, że szerokość diva to suma jego wartości width, grubości obramowania po obu stronach a także, uwaga: wielkość odstępu wewnętrznego czyli paddingu, także po obu stronach.</p>
<p><strong>A faktycznie, miałem tak ustawione! To pewnie dlatego. A już kiedyś bawiłem się wartościami float ale był przy tym same problemy. W momencie jeśli w divie był inny pływający obiekt to ten blok się zsuwał, miał zły rozmiar. Przez to float wszystkie elementy będące poniżej podnosiły się w górę. Dlaczego?</strong></p>
<p>To typowe. Jeśli w jakimś elemencie jest obiekt z ustawionym float to nie będzie on przyjmował prawidłowej wysokości. Będzie zachowywał się tak jakby tego pływającego elementu wcale tam nie było. Ale naprawienie tego jest proste. Wystarczy temu elementowi który się zsuwa nadać wartość CSS<em> overflow: hidden</em>. Wszystko powinno być od tego momentu dobrze.</p>
<p><strong>Ok, zostawmy już te divy. Mam jeszcze inny kłopot. Niedawno temu próbowałem stworzyć menu i  chciałem aby przestrzeń do kliknięcia była konkretnych rozmiarów. Próbowałem nadać elementowi a wysokość i szerokość ale nic nie działało. To błąd przeglądarki?</strong></p>
<p>Nie, Twój. Element a to obiekt liniowy więc nie można mu nadawać wymiarów. Ale w CSS istnieje atrybut <em>display</em> dzięki czemu można sprawić by każdy element zachowywał się tak jak chcemy. I żeby odnośnik zachowywał się jak blok i miał wymiary najzwyczajniej nadajemy mu wartość <em>display: block</em>.</p>
<p><strong>Dobra cwaniaku. To teraz mi powiedz w jaki sposób zrobić taki pasek na dole strony z na przykład newsami by nie ruszał się podczas przewijania strony. </strong></p>
<p>CCSem. Nadajesz paskowi <em>position: fixed</em> oraz <em>bottom: Ypx</em> gdzie Y to wysokość tego paska i wszystko będzie chodzić jak w szwajcarskim zegarku.</p>
<p><strong>No dobra, a w takim razie jak&#8230;</strong></p>
<p>Herbata mi się skończyła.</p>
<p><strong>I?</strong></p>
<p>Na dzisiaj już skończmy. Wrócimy do naszej rozmowy w przyszłości.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/07/rozmowa-z-wujkiem-marcinem-cz1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Jak mądrze dodawać zdarzenia JavaScript</title>
		<link>http://mgdevelop.pl/index.php/2010/07/jak-madrze-dodawac-zdarzenia-javasrcipt/</link>
		<comments>http://mgdevelop.pl/index.php/2010/07/jak-madrze-dodawac-zdarzenia-javasrcipt/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 13:22:57 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[iteracja]]></category>
		<category><![CDATA[onClick]]></category>
		<category><![CDATA[węzły]]></category>
		<category><![CDATA[zdarzenia]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=242</guid>
		<description><![CDATA[Obecnie wszystkie przeglądarki z powodzeniem obsługują typowe zdarzenia JavaScript. Nie znaczy to jednak, że możemy umieszczać je w kodzie naszej... <a href="http://mgdevelop.pl/index.php/2010/07/jak-madrze-dodawac-zdarzenia-javasrcipt/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Obecnie wszystkie przeglądarki z powodzeniem obsługują typowe zdarzenia JavaScript. Nie znaczy to jednak, że możemy umieszczać je w kodzie naszej strony jakkolwiek chcemy.  Dalej bowiem roboty wyszukiwarek analizują strony pomijając wszelkie skrypty. Nieprawidłowe podpinanie zdarzeń może także źle wpłynąć na odbiór aplikacji przez internautę. Jak uniknąć zatem problemów? O tym właśnie będzie ten poradnik.<span id="more-242"></span></p>
<h1>Przykład na linkach</h1>
<p>Do najczęściej używanych zdarzeń JavaScript należą <em>onClick</em>, <em>onMouseOver </em>i <em>onMouseOut</em>. Najprościej dodać je w ten sposób:</p>
<pre class="brush: html">&lt;a href="podstrona.html" onclick="jakas_funkcja(); return false"&gt;Kliknij&lt;/a&gt;</pre>
<p>W takim przypadku mamy wywołanie funkcji, za pomocą <em>return false;</em> blokujemy działanie linka a także w razie braku obsługi JS jesteśmy asekurowani przez odnośnik do pliku <em>podstrona.htm</em>l. Fajnie, ale IE7 strzeli nam focha. Poza tym nie jest to zbyt eleganckie rozwiązanie. Jak zaczniemy dodawać inne zdarzenia może dojść do niepotrzebnego bałaganu w kodzie.  A przecież mamy jeszcze <em>onBlur</em>, <em>onFocus</em>, <em>onChange </em>itd. Jak zatem zrobić by wszyscy byli zadowoleni? Już śpieszę pokazać:</p>
<pre class="brush: html">&lt;a href="podstrona.html" class="odnosnik"&gt;kliknij mnie!&lt;/a&gt;</pre>
<p>Pewnie wielu z was zapyta &#8222;Dobra, a gdzie kod?&#8221;. Właśnie cała sztuczka polega na tym by rozdzielić kod HTML od JavaScript i wpakować ten drugi do sekcji head. Samo zdarzenie zaś podepniemy na podstawie dodanej klasy <em>odnosnik</em>.</p>
<p>Poniższy kod należy wstawić do sekcji head. Działa on bardzo prosto. Najpierw wszystkie istniejące na stronie odnośniki zapisujemy w tablicy <em>elementya</em> a potem w pętli sprawdzamy w każdym czy ma klasę <em>odnosnik</em>. Jeśli tak to podpinamy pod zdarzenie <em>onClick </em>funkcję  <em>jakas_funkcja </em>pamiętając o pominięciu nawiasów po nazwie a także o umieszczeniu return false; na końcu naszej funkcji.</p>
<pre class="brush: javascript">var elementya = document.getElementsByTagName('a');
for(i=0; i &lt; elementya.length; i++) {
     if (elementya[i].className=='odnosnik') elementya[i].onclick = jakas_funkcja;
 }</pre>
<p>Zamiast pisać osobną funkcję możemy także stworzyć tzw. funkcję anonimową którą umieszcza się od razu w powyższym kodzie:</p>
<pre class="brush: javascript">var elementya = document.getElementsByTagName('a');
for(i=0; i &lt; elementya.length; i++) {
if (elementya[i].className=='odnosnik') elementya[i].onclick = function() { alert(';P'); return: false; };
}</pre>
<p>Dodaliśmy zaledwie trzy linijki kodu a mamy pewność, że wszystko będzie działało tak jak trzeba na każdej przeglądarce. W razie nie działania JavaScriptu nic także nie będzie przeszkadzać by adres spod linku normalnie się wyświetlił. Taki coś jest potrzebne przy na przykład tworzeniu Ajaxowych komentarzy. Fajnie jak się dodają bez odświeżania strony ale skrypt musi także obowiązkowo działać gdy użytkownik będzie miał zablokowane wykonywanie skryptów w przeglądarce.</p>
<h1>A bez href?</h1>
<p>Jeśli nasz skrypt nie wymaga href w trybie bez JS to możemy np. upodobnić do odnośników element span:</p>
<pre class="brush: html">&lt;script&gt;
    var elementy = document.getElementsByTagName('span');
    for(i=0; i &lt; elementy.length; i++) {
    if (elementya[i].className=='klikacz') elementy[i].onclick = function() { alert(';P'); return: false; };
}
&lt;/srcipt&gt;
&lt;style&gt;
   .klikacz{
        cursor: pointer;
   }
&lt;/style&gt;
&lt;span class="klikacz"&gt;Do złudzenia jak link&lt;/span&gt;</pre>
<p>W powyższym kodzie zmieniliśmy poszukiwane elementy na span a także za pomocą odpowiedniej klasy spowodowaliśmy, że najeżdzając na niego myszką kursor zamieni się na łapkę, tak jakby był to prawdziwy link.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/07/jak-madrze-dodawac-zdarzenia-javasrcipt/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Zakładkowe menu w CSS</title>
		<link>http://mgdevelop.pl/index.php/2010/06/zakladkowe-menu-w-css/</link>
		<comments>http://mgdevelop.pl/index.php/2010/06/zakladkowe-menu-w-css/#comments</comments>
		<pubDate>Tue, 29 Jun 2010 17:06:12 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[HTML i CSS]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=231</guid>
		<description><![CDATA[W tym krótki poradniku postaram się pokazać jak łatwo wykonać modne menu w kształcie zakładek bez potrzeby uruchamiania programu graficznego.... <a href="http://mgdevelop.pl/index.php/2010/06/zakladkowe-menu-w-css/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>W tym krótki poradniku postaram się pokazać jak łatwo wykonać modne menu w kształcie zakładek bez potrzeby uruchamiania programu graficznego. Efekt działa w Firefoxie, Chrome, Safari i Konquerorze3. Pozdrowienia z tego miejsca dla twórców Opery i Internet Explorera.<span id="more-231"></span></p>
<h1>Na początek HTML</h1>
<p>Nasze menu jak nakazuje dobry webdeveloperski obyczaj będzie opierało się na odpowiednio ostylowanej liście.</p>
<pre class="brush:html">&lt;ul class="menu"&gt;
  &lt;li&gt;&lt;a href="#"&gt;Homepage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#"&gt;Artykuly&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#" class="menu-active"&gt;Galeria&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#"&gt;Download&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#"&gt;O mnie&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="#"&gt;Kontakt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>Jak widać jednemu z elementów nadaliśmy dodatkową klasę <em>menu-active</em>. Za jej pomocą oznaczamy aktualnie aktywny element, to znaczy link do strony, na której jesteśmy. Całe menu oznaczyliśmy klasą <em>menu, </em> za pomocą której będziemy się odwoływać w arkuszu styli.</p>
<h1>Meritum czyli CSS</h1>
<p>Teraz zajmijmy się pisaniem opisu CSS. Po pierwsze zerujemy wszystkie odstępy w elemencie UL i usuwamy kropki sprzed elementów listy:</p>
<pre class="brush:css">.menu{
  margin: 0px;
  padding: 0px;
  list-style: none;
}</pre>
<p>Dalej ustawiamy elementy LI w jednym rzędzie i nadajemy ujemny prawy margines by zakładki na siebie nachodziły:</p>
<pre class="brush:css">.menu li{
  float: left;
  display: block;
  height: 30px;
  width: 100px;
  margin-right: -5px;
}</pre>
<p>Pora na ustawienie linków. Ważne jest aby wyświetlały się jako bloki (<em>display: block;</em>) i miały ustalone rozmiary i pozycję w wymiarze Z (<em>z-index: 1;</em>). Aby jednak nasze menu przybrało &#8222;zakładkowy&#8221; wygląd trzeba dodać na przykład zaokrąglone rogi. Ostatnie cztery wartości ustawiają zaokrąglenie dla prawego górnego rogu kolejno w:  Chromie/Safari, Konquerorze, Firefoxie i przeglądarkach zgodnych z CSS3. Dla przejrzystości kod pozbawiony jest opisów czcionek i kolorów</p>
<pre class="brush:css">.menu li a{
  display: block;
  height: 30px;
  width: 100px;
  position: relative;
  z-index: 1;
  -webkit-border-top-right-radius: 20px;
  -khtml-border-radius-topright: 20px;
  -moz-border-radius-topright: 20px;
   border-top-right-radius: 20px
}</pre>
<p>Teraz pozostaje jeszcze tylko opisać naszą dodatkową klasę menu-active. Jak już pisałem zakładka z taką klasą musi wystawać ponad pozostałe. Inaczej mówiąc musi być na wyższej pozycji w wymiarze Z. Normalnie zakładki mają pozycję 1, więc ta aktywna musi mieć większą:</p>
<pre class="brush:css">.menu a.menu-active{
  z-index: 2;
}</pre>
<p>I to wszystko. Zero grafiki, a efekt co najmniej ciekawy. Gotowy przykład można zobaczyć pod <a title="przykład na żywo" href="http://example.mgdevelop.pl/menucss.html">tym linkiem</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/06/zakladkowe-menu-w-css/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gravatar &#8211; avatary na zamówienie</title>
		<link>http://mgdevelop.pl/index.php/2010/06/gravatar-avatary-na-zamowienie/</link>
		<comments>http://mgdevelop.pl/index.php/2010/06/gravatar-avatary-na-zamowienie/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 21:35:13 +0000</pubDate>
		<dc:creator>Elektryk</dc:creator>
				<category><![CDATA[PHP & MySQL]]></category>

		<guid isPermaLink="false">http://mgdevelop.pl/?p=210</guid>
		<description><![CDATA[W jaki sposób przechowywać  avatary to dylemat nad którym musi zastanowić się każdy webdeveloper. Czy stworzyć rejestrację użytkowników i przechowywać... <a href="http://mgdevelop.pl/index.php/2010/06/gravatar-avatary-na-zamowienie/">Czytaj dalej&#187;</a>]]></description>
			<content:encoded><![CDATA[<p>W jaki sposób przechowywać  avatary to dylemat nad którym musi zastanowić się każdy webdeveloper. Czy stworzyć rejestrację użytkowników i przechowywać je u siebie czy może zrezygnować z nich całkowicie. A może jeszcze inaczej? Ja w tym poradniku chciałbym pokazać ciekawą alternatywę która ułatwia życie twórcom witryn internetowych i odciąża ich miejsce na serwerze. Mowa tu o Gravatarach.<span id="more-210"></span></p>
<p>Grupa Automattic to to twórcy systemu WordPress. Wraz z rozrostem ich platformy blogowej pojawiła się potrzeba obsługi avatarów, małych obrazków które pozwalają na wizualną identyfikacje komentujących. WordPress nigdy jednak nie słynął z rozbudowanego systemu użytkowników. Dlatego postanowiono przenieść ten moduł na nowo powstałą platformę Gravatar.com skąd avatary mogą być pobieranie przez wszystkie instalacje WP. Co ważne dostęp do tej bazy obrazków mają nie tylko WordPressy ale każda inna strona internetowa. Co więcej implementacja tej usługi jest bardzo prosta a cały system jest przyjazny użytkownikom.</p>
<h1>Tworzenie gravataru</h1>
<p>Serwis Gravatar jest intuicyjny w obsłudze. Po rejestracji (lub zalogowaniu się danymi z wordpress.com) możemy załadować na jego serwer swój avatar i przypisać go do swojego adresu konta pocztowego. Na ten adres dostaniemy po chwili e-mail z linkiem. Klikając na niego potwierdzimy, że jesteśmy posiadaczami tego loginu. Od tej chwili nasz avatar będzie chodził po internecie za nami. Wystarczamy, że pisząc komentarz podamy ten sam adres e-mail a nasz avatar pojawi się obok naszej opinii. Oczywiście tylko na serwisach korzystających z bazy gravatarów.</p>
<h1>Od strony webdevelopera</h1>
<p>Usługa oferowana przez serwis Gravatar niesamowicie upraszcza życie twórcom witryn internetowych. By mieć w komentarzach avatary nie musimy już tworzyć systemu rejestracji i ładowania grafik. Wystarczy pobrać od użytkownika jego e-mail i zapisać go w bazie danych. Odpowiedni, krótki skrypt dodany do kodu wyświetlającego komentarze załatwi resztę sprawy.</p>
<h1>Kod czyli zapraszamy avatary do siebie</h1>
<p>Gravatary można zaimplementować do kodu w każdym języku skryptowym. Ja pokaże jak zrobić to na przykładzie PHP ale równie dobrze można to zrobić w Pythonie, Ruby, JavaScripcie czy C#.</p>
<p>Cały proces polega na tym by skleić odpowiedni adres do obrazka tak by zawierał e-mail internaty oraz ustawienia. Adres trzeba zakodować za pomocą funkcji <em>md5()</em> aby nie był widoczny w kodzie dla botów spamerów. Najprostzy kod wygląda tak:</p>
<pre class="brush:php">&lt;?php
   $email = md5(strtolower("adres@emailowy.usera"));
   $gravatar = "http://www.gravatar.com/avatar/".$email
?&gt;
&lt;img src="&lt;?php echo $gravatar; ?&gt;" alt="Avatar"&gt;</pre>
<p>W powyższym kodzie dodatkowo przepuściliśmy adres przez funkcję <em>strtolower()</em> by mieć pewność, że wszystkie znaki są z małej litery. Proponuję się przyjrzeć jak wygląd ma adres obrazka. W chwili obecnej nasza grafika nie ma rozszerzenia, kończy się hashem. Ale w usłudze gravatar nie ma problemu z rozszerzeniem, można je spokojnie dodać. Wygląda to wtedy bardziej elegancko a w niektórych skryptach rozszerzenie jest wymagane.</p>
<pre class="brush:php">$gravatar = "http://www.gravatar.com/avatar/".$email.".jpg"</pre>
<h1>Dostosowywanie wyglądu</h1>
<p>Powyższy kod zalinkuje do obrazków o rozmiarze 80 na 80 pikseli. Gdybyśmy potrzebowali innych wymiarów to możemy w łatwy sposób to ustawić.</p>
<pre class="brush:php">&lt;?php
   $email = md5(strtolower("adres@emailowy.usera"));
   $gravatar = "http://www.gravatar.com/avatar/".$email."?size=120";
?&gt;
&lt;img src="&lt;?php echo $gravatar; ?&gt;" alt="Avatar"&gt;</pre>
<p>W tym przykładzie ustawliśmy rozmiar grafik na 120x120px. A co jeśli komentujący nie ustawił sobie gravataru? Wtedy możemy ustawić domyślny obrazek:</p>
<pre class="brush:php">&lt;?php
   $email = md5(strtolower("adres@emailowy.usera"));
   $domyslne = "http://www.moja-strona.pl/avatar.jpg";
   $gravatar = "http://www.gravatar.com/avatar/".$email."?&amp;default=".$domyslne;
?&gt;
&lt;img src="&lt;?php echo $gravatar; ?&gt;" alt="Avatar"&gt;</pre>
<p>Od teraz przy każdym użytkowniku który nie ma ustawionego gravatara będzie pojawiał się obrazek spod adresu<em> http://www.moja-strona.pl/avatar.jpg</em>. Może to spowodować jednak małe zamieszanie dlatego Gravatar.com pozwala by domyślnie był wyświetlany obrazek generowany na podstawie literek w adresie e-maila. Brzmi to dziwnie ale naprawdę działa i co więcej jest dostępne w trzech opcjach. Aby uaktywnić tą funkcję zamiast adresu podajemy <em>identicon</em>, <em>monsterid</em> lub <em>wavatar.</em></p>
<pre class="brush:php">$gravatar = "http://www.gravatar.com/avatar/".$email."?&amp;default=wavatar";</pre>
<p>Ale to jeszcze nie wszystko. Gravatar obsługuje klasyfikacje obrazków dzięki czemu możemy zapobiec by na naszej stronie nie pojawiały się zbyt frywolne grafiki. Domyślna klasyfikacja to G czyli obrazki dla wszystkich, PG to obrazki mogące zawierać niestosowne gesty lub lekką przemoc, R należy kojarzyć z narkotykami, nagością i profanacją a X to&#8230;hulaj dusza, piekła niema. W kodzie konfiguruje się to następująco:</p>
<pre class="brush:php">$gravatar = "http://www.gravatar.com/avatar/".$email."?&amp;rating=x";</pre>
<p>Oczywiście wszystkie powyższe opcje można dowolnie łączyć, o to przykład takiego połączenia:</p>
<pre class="brush:php">&lt;?php
   $email = md5(strtolower("adres@emailowy.usera"));
   $gravatar = "http://www.gravatar.com/avatar/".$email."?&amp;rating=x&amp;default=monsterid&amp;size=50";
?&gt;
&lt;img src="&lt;?php echo $gravatar; ?&gt;" alt="Avatar"&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://mgdevelop.pl/index.php/2010/06/gravatar-avatary-na-zamowienie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

