<?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>j2ee.pl - związani z javą &#187; widget</title>
	<atom:link href="http://j2ee.pl/tag/widget/feed/" rel="self" type="application/rss+xml" />
	<link>http://j2ee.pl</link>
	<description>związani z Javą</description>
	<lastBuildDate>Mon, 24 Aug 2009 11:45:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Widgety &#8211; część druga: WidSets</title>
		<link>http://j2ee.pl/2008/08/21/widgety-czesc-druga-widsets/</link>
		<comments>http://j2ee.pl/2008/08/21/widgety-czesc-druga-widsets/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 14:28:10 +0000</pubDate>
		<dc:creator>Maciej Żywioł</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[WebServices]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[widsets]]></category>

		<guid isPermaLink="false">http://j2ee.pl/?p=246</guid>
		<description><![CDATA[Universal Widget API, o którym opowiadałem poprzednio, jest dość wszechstronny i faktycznie działa na wielu platformach, jednak jego zawarta w nazwie uniwersalność ma pewne ograniczenia. Najpoważniejszym z nich jest brak kompatybilności z urządzeniami mobilnymi – działają tylko pod iPhone’em, a Opera Mobile dla &#8220;normalnych&#8221; telefonów jeszcze z nimi nie współpracuje.
Dla chcących pisać widgety na bardziej [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://j2ee.pl/wp-content/uploads/2008/08/widsets1.gif"><img class="alignnone size-medium wp-image-254" title="widsets1" src="http://j2ee.pl/wp-content/uploads/2008/08/widsets1.gif" alt="" width="109" height="36" align="left" /></a>Universal Widget API, o którym opowiadałem poprzednio, jest dość wszechstronny i faktycznie działa na wielu platformach, jednak jego zawarta w nazwie uniwersalność ma pewne ograniczenia. Najpoważniejszym z nich jest brak kompatybilności z urządzeniami mobilnymi – działają tylko pod iPhone’em, a Opera Mobile dla &#8220;normalnych&#8221; telefonów jeszcze z nimi nie współpracuje.</p>
<p>Dla chcących pisać widgety na bardziej pospolite telefony komórkowe jest nadzieja w postaci platformy <a href="https://www.widsets.com/index.html" target="_blank"><strong>WidSets</strong></a>, uruchomionej i wdrożonej przez koncern Nokia, jednak nie tylko na telefony tej firmy przeznaczona.<span id="more-246"></span></p>
<h2>Użytkowanie</h2>
<p>Platforma WidSets współpracuje <a href="https://www.widsets.com/info/compatibility.html" target="_blank">z ponad trzema setkami modeli</a> telefonów komórkowych i opiera się o aplikację, którą w telefonie należy sobie zainstalować. Aplikacja ta łączy się z naszym kontem, założonym w internetowym serwisie WidSets, pobiera dane o wybranych przez nas widgetach i wyświetla je na ekranie naszego telefonu.</p>
<p>Oczywiście, najpierw trzeba sobie w serwisie założyć owo konto. Zanim to jednak zrobimy, serwis WidSets udostępnia nam bardzo ciekawie pomyślaną <a href="https://www.widsets.com/getstarted.html" target="_blank">demonstrację</a> swoich możliwości &#8211; na specjalnej stronie mamy dostępną całą bibliotekę widgetów do wyboru, oraz emulator telefonu komórkowego, na którym możemy podpatrzeć, jak aplikacja będzie wyglądać i działać.</p>
<p>Gdy już zdecydujemy się na <a href="https://www.widsets.com/register.html" target="_blank">rejestrację</a>, będziemy przez jej proces poprowadzeni jak za rączkę &#8211; serwis najpierw pyta o typowe dane rejestracyjne, a następnie pomaga nam pobrać i zainstalować aplikację w telefonie. Trzeba przyznać, że to także jest świetnie rozwiązane &#8211; dostępne są trzy drogi, do wyboru w zależności od stopnia zaawansowania użytkownika, w różnym stopniu absorbujące jego uwagę:</p>
<ul>
<li><strong>Dummies</strong> podają numer telefonu, na który przychodzi sms z linkiem, pod którym znajduje się aplikacja do zainstalowania,</li>
<li><strong>Techies</strong> przepisują podany na stronie URL do przeglądarki w komórce,</li>
<li>a <strong>Geeks</strong> pobierają plik JAD, który ręcznie przenoszą i odpalają w telefonie, instalując tym samym aplikację.</li>
</ul>
<p>Ja wybrałem to środkowe rozwiązanie, co pozwoliło nie czuć mi się ani jak oporny (dummy), ani jak geek.</p>
<p>Po zainstalowaniu w telefonie, aplikacja łączy się z kontem w serwisie i można przejść do konfiguracji, która polega głównie na wybraniu z biblioteki interesujących nas widgetów. <a href="https://www.widsets.com/library.html" target="_blank">Biblioteka</a> jest dość obszerna i zawiera mnóstwo programów przydatnych bardziej (wiadomości, pogoda, organizatory czasu, skrzynki e-mailowe&#8230;) lub mniej (gry i inne czasoumilacze). Bardzo fajne jest to, że swoje widgety można wybierać nie tylko za pośrednictwem telefonu, ale też w komputerze, logując się w serwisie &#8211; nawet, gdy nasz telefon nie jest z nim połączony, my możemy zobaczyć i skonfigurować nasz pulpit (<em>dashboard</em>), a nawet &#8211; odpalić emulator komórki, w którym możemy przetestować jego działanie.</p>
<p>Testowałem działanie WidSetsów na mojej Nokii E50 i wszystko działa bardzo dobrze. Dodatkowe ułatwienie, podejrzewam, mogą mieć posiadacze telefonów z wbudowanym WiFi (np. Nokia E51), którzy nie muszą się łączyć z internetem za pośrednictwem swojej sieci komórkowej.</p>
<h2>Tworzenie</h2>
<p>Jak większość serwisów widgetowych (NetVibes, Opera, Apple&#8230;), także WidSets udostępniają możliwość tworzenia własnych widgetów. Przede wszystkim w serwisie dostępna jest opcja szybkiego generowania widgeta. Ma on, oczywiście, ograniczone możliwości &#8211; można w nim stworzyć właściwie tylko czytnik kanałów RSS lub podobnych i najwyżej wybrać skórkę, która nam będzie odpowiadać &#8211; ale niektórym to w zupełności wystarcza (coś podobnego, ale dla widgetów &#8220;desktopowych&#8221;, oferuje serwis <a href="http://www.wstaw.to/wstawTo/1,88931,5166677.html" target="_blank">wstaw.to</a>).</p>
<p>Dla użytkowników bardziej wymagających i tych z zacięciem programistycznym, WidSets oferują cały <a href="http://wiki.forum.nokia.com/index.php/WidSets_SDK" target="_blank">Software Developer&#8217;s Kit</a> do tworzenia bardziej zaawansowanych programów. Taki wdget składa się z dwóch plików: XML-owego deskryptora (plik <em>widget.xml</em>) oraz z kodu aplikacji (plik <em>*.he</em>). Dodatkowo mogą się na niego składać pliki zasobów, np. obrazki w formacje jpg lub png.</p>
<p>Plik <a href="http://wiki.forum.nokia.com/index.php/Developing_your_first_WidSets_widget#Create_the_widget.xml" target="_blank"><strong>widget.xml</strong></a> zawiera informacje o naszym widgecie: w sekcji &lt;info&gt; znajdują się informacje o widgecie, np:</p>
<pre class="prettyprint"> &lt;info&gt;
   &lt;name&gt;Flag Selector&lt;/name&gt;
   &lt;version&gt;1.0&lt;/version&gt;
   &lt;author&gt;Developer&lt;/author&gt;
   &lt;shortdescription&gt;Displaying some flags&lt;/shortdescription&gt;
 &lt;/info&gt;</pre>
<p>Następnie w sekcji &lt;parameters&gt; opisane są opcje i parametry widgeta &#8211; analogicznie do taga &lt;widget:preferences&gt; w UWA:</p>
<pre class="prettyprint"> &lt;parameters&gt;
   &lt;parameter type="string"
                name="widgetname"
                description="Name of widget"
                help="This is the name of the widget"
                editable="false"
                sendtomobile="true"
                visible="true"&gt;
     &lt;value&gt;
       Flag Selector
     &lt;/value&gt;
   &lt;/parameter&gt;
 &lt;/parameters&gt;</pre>
<p>Następnie, w sekcji &lt;resources&gt; wymienione są dodatkowe źródła danych, np. style, z których aplikacja będzie korzystać (składniowo podobne do CSS), np:</p>
<pre class="prettyprint">&lt;stylesheet&gt;
   bkg {
     background: vgradient white silver;
   }

   frame {
     background: solid silver;
   }

   flag {
     align: hcenter vcenter;
     border: 2 2 2 2;
     border-type: rectangle red;
   }

   nametext {
     align: hcenter vcenter;
     color-1: green;
     font-1: medium bold;
     background: vgradient silver white;
   }

   greetingtext {
     align: hcenter vcenter;
     color-1: blue;
     font-1: medium bold;
     background: vgradient white green;
   }

   about {
     align: hcenter vcenter;
     color-1: blue;
     font-1: large bold;
     background: solid orange;
   }
 &lt;/stylesheet&gt;</pre>
<p>albo pliki zasobów, np. graficznych:</p>
<pre class="prettyprint"> &lt;img scale=”true” src="finland.png"/&gt;
 &lt;img scale=”true” src="uk.png"/&gt;
 &lt;img scale=”true” src="eu.png"/&gt;
 &lt;img src="bkg.png"/&gt;</pre>
<p>Wreszcie &#8211; podany tam jest plik (tylko jeden) z kodem źródłowym widgeta:</p>
<pre class="prettyprint"> &lt;code src=”flagselector.he”/&gt;</pre>
<p>W ostatniej sekcji deskryptora, &lt;layout&gt;, wymienione i opisane są widoki widgeta, których zasadami wyświetlania zajmuje się skrypt aplikacji. Elementy graficzne podobne są do komponentów Swingowych:</p>
<pre class="prettyprint"> &lt;layout minimizedheight="60px"&gt;
   &lt;view id="miniView"&gt;
     &lt;img src="minimized.png"/&gt;
   &lt;/view&gt;
   &lt;view class="bkg" id="mainView"&gt;
     &lt;script id="flag" top="10%" right="80%" bottom="60%" left="20%"/&gt;
     &lt;script id="name" top="65%" right="100%" bottom="80%" left="0%"/&gt;
     &lt;script id="greeting" top="80%" right="100%" bottom="100%" left="0%"/&gt;
   &lt;/view&gt;
 &lt;/layout&gt;</pre>
<p>Gdy już deskryptor mamy napisany, pora zasiąść do kodu właściwego. Piszę się go w języku skryptowym WSL, czyli <a href="http://wiki.forum.nokia.com/index.php/WidSets_Scripting_Language" target="_blank"><strong>WidSets Scripting Language</strong></a>. Jest on podobny w składni do Javy, choć mocno ograniczony. Cały kod widgeta opiera się na klasie, w której musimy zdefiniować metody startWidget() oraz openWidget() &#8211; od nich rozpoczyna działanie nasza aplikacja. Przepływ programu polega na odpowiednim odnoszeniu się do zdefiniowanych w deskryptorze, w sekcji &lt;layout&gt;, widoków i elementów. Mamy też możliwość sięgania po zdefiniowane tam zasoby i parametry, a także możemy definiować akcje klawiszy telefonu komórkowego.</p>
<p>Bardzo istotnym elementem API są usługi pobierania treści &#8211; nasz widget może być czymś więcej, niż lokalną aplikacją, działającą na lokalnych danych (jak gra bądź kalkulator). Możliwe jest sięganie do danych z różnych usług webowych. Dostępne są cztery rodzaje usług:</p>
<ul>
<li><a href="http://wiki.forum.nokia.com/index.php/Syndication_service" target="_blank"><strong>Syndication</strong></a> do pobierania treści z kanałów RSS, Atom czy RDF,</li>
<li><a href="http://wiki.forum.nokia.com/index.php/Webfeed_service" target="_blank"><strong>Webfeed</strong></a> do pobierania niestandardowych treści,</li>
<li><a href="http://wiki.forum.nokia.com/index.php/Image_service" target="_blank"><strong>Image</strong></a> do pobierania grafiki, oraz</li>
<li><a href="http://wiki.forum.nokia.com/index.php/HTTP_service" target="_blank"><strong>HTTP</strong></a> do wykonywania żądań HTTP GET i HTTP POST.</li>
</ul>
<p>Dzięki temu, oraz dodatkowym usługom (np. <a href="http://wiki.forum.nokia.com/index.php/HTTP_authentication" target="_blank">autentykacji</a>) można stworzyć widgeta, który będzie sięgał do różnych źródeł internetowych, pobierał i kompilował interesujące nas dane, a następnie wyświetlał w przystępnej formie na ekranie naszego telefonu.</p>
<h2>Użytkowanie tego, co się stworzyło</h2>
<p>Gdy już skrypt i deskryptor mamy napisane, możemy przejść do kompilacji, testowania, a wreszcie &#8211; umieszczenia na swoim pulpicie. Kompilator jest dołączony do SDK w postaci programu devkit, uruchamianego z linii komend. Na początek musimy zalogować się na swoje konto w serwisie WidSets:</p>
<pre class="prettyprint">devkit login [LOGIN] [HASŁO]</pre>
<p>a następnie wydajemy jedną komendę:</p>
<pre class="prettyprint">devkit run [ŚCIEŻKA_DO_WIDGETA]</pre>
<p>a program naszego widgeta skompiluje, spakuje do ZIPa, wyśle do serwisu i uruchomi emulator komórki, w którym możemy widgeta przetestwować od razu. Ponieważ widget jest od razu wrzucany na nasz WidSetsowy pulpit, możemy go także od razu przetestować w prawdziwym telefonie.</p>
<p>Kompilator devkit posiada jeszcze mnóstwo dodatkowych opcji, ale nie będę się w nie tutaj zagłębiał. Dość powiedzieć, że daje on całkiem pokaźne możliwości.</p>
<p>Po pozytywnym przetestowaniu nasz widget możemy dodać do biblioteki publicznej, aby inni też mogli go sobie pobrać i z niego korzystać, ale nie jest to oczywiście konieczne.</p>
<h2>Podsumowanie</h2>
<p>WidSets jest naprawdę ciekawą technologią, pozwalającą na tworzenie małych, prostych a użytecznych aplikacji, do których można mieć dostęp wszędzie za pośrednictwem telefonu komórkowego. Mogą mieć zarówno charakter lokalny (czyli przetwarzać dane, wprowadzane bezpośrednio do telefonu albo korzystać z jego zasobów &#8211; istnieje np. możliwość pobierania danych z aparatu fotograficznego w telefonie), jak i zdalny, gdy aplikacja sięga po zasoby lub informacje z Internetu, by je obrobić i wyświetlić.</p>
<h2>Źródła</h2>
<ul>
<li><a href="http://wiki.forum.nokia.com/index.php/Category:WidSets" target="_blank">WidSets Wiki</a>
<ul>
<li><a href="http://wiki.forum.nokia.com/index.php/Developing_your_first_WidSets_widget" target="_blank">Pierwsza aplikacja</a> (stąd brałem fragmenty kodu do przykładów w artykule)</li>
<li><a href="http://wiki.forum.nokia.com/index.php/WidSets_Scripting_Language" target="_blank">WSL w skrócie</a></li>
<li><a href="http://wiki.forum.nokia.com/index.php/WidSets_SDK" target="_blank">Opis WidSets SDK</a></li>
</ul>
</li>
<li><a href="http://www.forum.nokia.com/document/WidSets_APIdocs/" target="_blank">WidSets API &#8211; dokumentacja</a> a&#8217;la Javadoc</li>
<li><a href="http://www.forum.nokia.com/main/resources/tools_and_sdks/widsets/" target="_blank">WidSets SDK </a>- pobieranie</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://j2ee.pl/2008/08/21/widgety-czesc-druga-widsets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Widgety &#8211; część pierwsza: Universal Widget API</title>
		<link>http://j2ee.pl/2008/08/18/widgety-czesc-pierwsza-universal-widget-api/</link>
		<comments>http://j2ee.pl/2008/08/18/widgety-czesc-pierwsza-universal-widget-api/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 13:36:54 +0000</pubDate>
		<dc:creator>Maciej Żywioł</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[WebServices]]></category>
		<category><![CDATA[universal widget api]]></category>
		<category><![CDATA[uwa]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://j2ee.pl/?p=222</guid>
		<description><![CDATA[
Widgety – małe aplikacje użytkowe lub rozrywkowe, po polsku zwane często gadżetami – można spotkać coraz częściej, zarówno w sieci – na widgetach oparte są serwisy stron startowych (personalized homepages), jak NetVibes czy iGoogle – jak i poza nią, w aplikacjach desktopowych (panel gadgetów w Windows Vista albo Apple Dashboard pod Mac OSem), a nawet [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://j2ee.pl/wp-content/uploads/2008/08/netvibes2.png"><img class="alignnone size-medium wp-image-242" title="netvibes2" src="http://j2ee.pl/wp-content/uploads/2008/08/netvibes2.png" alt="" width="174" height="40" align="left"/></a></p>
<p>Widgety – małe aplikacje użytkowe lub rozrywkowe, po polsku zwane często gadżetami – można spotkać coraz częściej, zarówno w sieci – na widgetach oparte są serwisy stron startowych (<em>personalized homepages</em>), jak <a href="http://www.netvibes.com/" target="_blank">NetVibes</a> czy <a href="http://www.google.com/ig" target="_blank">iGoogle</a> – jak i poza nią, w aplikacjach desktopowych (panel gadgetów w Windows Vista albo <a href="http://www.apple.com/pl/downloads/dashboard/" target="_blank">Apple Dashboard</a> pod Mac OSem), a nawet w telefonie komórkowym. Każdy z wymienionych serwisów widgetów istniał jednak osobno – iGoogle, NetVibes, Apple czy Opera (która <a href="http://widgets.opera.com/general/faq/#widgets-run" target="_blank">od wersji 9</a> także wspiera widgety) miały swoje technologie i swoje zbiory gadżetów do pobrania i wykorzystania. Niektóre z nich udostępniały te technologie wszystkim, pragnącym samemu napisać jakąś małą aplikację, tym samym powiększając bibliotekę danego serwisu, ale cały czas taki twórczy użytkownik ograniczony był tylko do jednej platformy.<br />
Dlatego też NetVibes – pionier w dziedzinie owych stron startowych – postanowił przerobić swój MiniAPI 0.3, w którym wcześniej można było pisać moduły do zamieszczania w ich serwisie, na nowy API, który został zaprezentowany w wersji 1.0 pod nazwą <a href="http://dev.netvibes.com/" target="_blank">Universal Widget API</a>.<span id="more-222"></span></p>
<h2>Z czym to się je?</h2>
<p>Pierwszą i najważniejszą zaletą Universal Widget API (w skrócie UWA) jest – jak sama nazwa wskazuje – jego <a href="http://dev.netvibes.com/doc/universal_widget_api" target="_blank">uniwersalność</a>. W tej chwili napisane w nim widgety można zamieścić nie tylko na stronie NetVibes, ale także z powodzeniem zaimportować na stronach iGoogle czy Live.com, umieścić na pasku gadżetów Visty czy MAC OSa, według twórców działają też na iPhone oraz pod Operą desktopową (Opera na urządzenia mobilne jeszcze <a href="http://widgets.opera.com/general/faq/#widgets-usemobile" target="_blank">nie jest na nie gotowa</a>), ale tych ostatnich nie udało mi się uruchomić (nie jestem użytkownikiem Opery, a jej mechanizm importowania widgetów stanowi dla mnie barierę nie do przeskoczenia), a zapowiadanych jest jeszcze więcej platform (m.in. Facebook czy wspomniana Opera Mobile). Dodatkowo taki gadżet można umieścić w ramce (<em>iframe</em>) na dowolnej stronie, np. na blogu.<br />
Napisany pod UWA widget stanowi kombinację HTMLa (rzecz jasna z CSSem), JavaScripta i AJAXa &#8211; te technologie wystarczą do napisania całego, działającego widgeta. Dodatkowo możliwości widgeta można znacznie rozszerzyć, podpinając go pod zewnętrzny skrypt PHP czy JSP albo pod WebService oparty na dowolnej technologii.<br />
Dość prostym przykładem jest czytnik RSS – w UWA można go zawrzeć w pojedynczym pliku XHTML:</p>
<pre class="prettyprint">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:widget="http://www.netvibes.com/ns/"&gt;
&lt;head&gt;
  &lt;title&gt;RSS Reader&lt;/title&gt;

  &lt;link rel="stylesheet" type="text/css" href="http://www.netvibes.com/themes/uwa/style.css" /&gt;
  &lt;script type="text/javascript" src="http://www.netvibes.com/js/UWA/load.js.php?env=Standalone"&gt;&lt;/script&gt;

  &lt;widget:preferences&gt;
    &lt;preference name="url" type="text" label="URL" defaultValue="http://j2ee.pl/feed/" /&gt;
    &lt;preference name="limit" type="range" label="Number of items to display" defaultValue="10" step="1" min="1" max="25" /&gt;
  &lt;/widget:preferences&gt;
  &lt;script type="text/javascript"&gt;
    var RSSReader = {}

    RSSReader.feed = false;
    RSSReader.display = function(feed) {
      if(feed) RSSReader.feed = feed;
      var feedList = widget.createElement('ul');
      feedList.className = 'nv-feedList';
      var j = 0;
      for(var i=0; i &lt; RSSReader.feed.items.length; i++) {
        if(j &gt;= widget.getValue('limit')) break;
        var item = RSSReader.feed.items[i];
        var li = widget.createElement('li');
        var a = widget.createElement('a');
        a.href = item.link;
        a.target = '_blank';
        var displayTitle = item.title;
        if(search != '') {
          displayTitle = String.highlight(displayTitle, search);
        }
        a.innerHTML = displayTitle;
        var title = item.content.stripTags().truncate(255);
        a.desc = title;
        a.onmouseover = function() {
          UWA.Utils.setTooltip(this, this.desc, 250);
        }
        li.appendChild(a);
        var display = true;
        if(display) { feedList.appendChild(li); j++;
      }
    }
    widget.setBody(feedList);
  }
  widget.onLoad = function() {
    widget.log('RSSReader.onLoad');
    UWA.Data.getFeed(widget.getValue('url'), RSSReader.display);
  }
  widget.onRefresh = widget.onLoad;
&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;p&gt;Loading ...&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h2>Przepis na gadżet</h2>
<p>Rdzeniem napisanego w UWA widgeta jest pojedynczy, statyczny plik XHTML, zawierający w nagłówku odniesienie do przestrzeni nazw NetVibes:</p>
<pre class="prettyprint"> xmlns:widget=“http://www.netvibes.com/ns/”</pre>
<p>Następnie w nagłówku strony należy umieścić w tagu <strong>preferences</strong> opcje widgeta – takie, które będą dostępne dla użytkownika po kliknięciu odpowiedniego linka na stronie (w zależności od platformy link ten może wyglądać inaczej):</p>
<pre class="prettyprint"> &lt;widget:preferences&gt;
  &lt;preference name="url" type="text" label="URL" defaultValue=" http://j2ee.pl/feed/" /&gt;
  &lt;preference name="limit" type="range" label="Number of items to display" defaultValue="7" step="1" min="1" max="10" /&gt;
 &lt;/widget:preferences&gt;</pre>
<p>Oczywiście, posiadanie właściwości nie jest niezbędne – można napisać widget bez żadnych opcji dostępnych dla użytkownika. Wtedy po prostu pozostawia się tag pusty:</p>
<pre class="prettyprint"> &lt;widget:preferences/&gt;</pre>
<p>Aktualnie UWA udostępnia kilka typów opcji, opartych na rodzajach pól w HTML-owych formularzach: <strong>text</strong>, <strong>password</strong>, <strong>boolean</strong> (odpowiednik <strong>checkbox</strong>), <strong>list </strong>(odpowiednik <strong>select</strong>), <strong>range </strong>(coś jak <strong>list</strong>, tylko z automatycznie generowanymi wartościami liczbowymi) i <strong>hidden</strong>. Trwają pracę nad obsłużeniem pól typu <strong>textarea</strong>. Wartości owych właściwości mogą zostać wykorzystane we właściwym javascriptowym kodzie widgeta w dalszej części strony za pomocą metody <strong>getValue </strong>obiektu <strong>widget</strong>.</p>
<h2>Danie główne &#8211; obiekty widget i UWA</h2>
<p>Kod javascriptowy kręci się wokół obiektu <strong>widget</strong>, którego metody analogiczne do zdarzeń (<strong>onLoad</strong>, <strong>onRefresh </strong>i inne) zawierają lub wywołują właściwy kod programu. Najczęściej – jeśli widget nie jest tylko lokalną aplikacją (np. grą), tylko sięga do zewnętrznych źródeł danych – kod ten zawiera jedną z dostarczanych przez UWA AJAXowych metod pobierania danych. W przykładzie, w metodzie <strong>onLoad </strong>można to znaleźć w linijce:</p>
<pre class="prettyprint"> UWA.Data.getFeed(widget.getValue('url'), RSSReader.display);</pre>
<p>Obiekt <strong>UWA.Data </strong>dostarcza kilka podobnych metod do wyboru. <strong>UWA.Data.getText() </strong>zwraca odpowiedź w formacie plain text, <strong>getXml() </strong>– w formacie XML, <strong>getJson() </strong>– w formacie danych <a href="http://www.json.org/" target="_blank">JSON</a>, <strong>getFeed()</strong> jest formą tego ostatniego, z tym, że JSONowa odpowiedź dodatkowo jest kompatybilna ze wszystkimi formatami źródeł danych – RSS, Atom i inne. Wszystkie metody pobierają dwa argumenty – adres źródła danych oraz nazwę funkcji, do której ma zostać przesłana odpowiedź (w przykładzie naszego czytnika RSS jest to metoda <strong>RSSReader.display()</strong>). Dodatkowo obiekt <strong>UWA.Data </strong>posiada metodę <strong>request()</strong>, która pobiera argumenty w postaci adresu oraz obiektu, przechowującego szczegóły żądania. Tak naprawdę wszystkie wymienione wcześniej metody (<strong>getText</strong>, <strong>getFeed </strong>itp.) są odpowiednio przeładowaną metodą <strong>request</strong>. Metody tej w czystej postaci używa się przy bardziej zaawansowanych potrzebach.<br />
Same źródła natomiast mogą być zupełnie dowolne – pod adresem, przekazywanym do metody, może znajdować się (jak w naszym przykładzie) kanał RSS, ale może to być dowolna inna zawartość (np. skrypt PHP, ASP czy JSP) generująca odpowiedź w odpowiednim formacie. Może to być, jak już wspomniałem, skrypt specjalnie na potrzeby tego widgeta napisany.<br />
Wracając do naszego przykładu &#8211; skoro już metoda <strong>getFeed </strong>zwróciła nam JSONowy obiekt z podanego adresu, przyjrzyjmy się metodzie, do której odpowiedź z serwera jest przekazywana. Metoda display przetwarza zawartość zwróconego obiektu <strong>feed </strong>i na jego podstawie buduje ciało strony. Używane są do tego metody obiektu <strong>widget </strong>takie, jak <strong>createElement</strong>, tworząca element HTMLowy podanego jako argument typu (np. <strong>widget.createElement(’a’) </strong>stworzy odnośnik) oraz metod obiektów reprezentujących owe elementy (<strong>addContent</strong>, <strong>setHTML</strong>, <strong>setStyle</strong>…). W ten sposób tworzona jest struktura DOM dokumentu, która, gdy już będzie gotowa, ładowana jest do ciała strony metodą <strong>widget.setBody</strong>, zastępując aktualną jego zawartość (dlatego jedyną zawartością znacznika <strong>&lt;body&gt; </strong>jest tymczasowy tekst „Loading…”, który znika po tym, jak metoda display przetworzy odpowiedź na żądanie).</p>
<h2>Deser – skrypty wykonywane po stronie serwera</h2>
<p>Jak już wspomniałem, widget może sięgać do źródeł danych specjalnie dla niego utworzonych, np. skryptów PHP. Jako przykład podam widgeta, pobierającego dane nie z jednego, a z wielu kanałów Atom (w tym przypadku – blogów z serwisu Blogger, których adresy przechowywane są w pliku myfeed.txt) i informujący o tym, kiedy każdy z nich był ostatnio aktualizowany.</p>
<p>Poniżej cytuję sam kod JavaScript z pliku XHTML widgeta. Nie korzysta on z żadnych ustawień (preferences) widgeta, więc obudowanie go odpowiednim kodem XHTML, wzorowanym choćby na powyższym przykładzie czytnika RSS, nie będzie trudne:</p>
<pre class="prettyprint">&lt;script type="text/javascript"&gt;
var xmlHttp = false;
var blogNote = false;
var MyFeed = {
  feed : false,
  feedArray : false,
  oneFeed : false,
  processFeed : function(feed) {
    widget.log(feed);
  }
}

MyFeed.parseFeeds = function(feed) {
  if(feed) MyFeed.feed = feed;
  widget.log(feed);
  var feedList = widget.createElement('ul');
  feedList.className = 'nv-feedList';
  feedArray = new Array();
  for(var i=0;i&lt;MyFeed.feed.list.length;i++) {
    var li = widget.createElement('li');
    var titleTxt = widget.createElement('a');
    titleTxt.className = 'myFeed_blogTitle';
    titleTxt.href = MyFeed.feed.list[i].url;
    titleTxt.target = '_blank';
    titleTxt.innerHTML = MyFeed.feed.list[i].title;
    li.appendChild(titleTxt);
    li.appendChild(widget.createElement('br'));
    var dateTxt = widget.createElement('span');
    dateTxt.className = 'myFeed_when';
    dateTxt.innerHTML = MyFeed.getWhen(MyFeed.feed.list[i].entry_when);
    li.appendChild(dateTxt);
    li.appendChild(widget.createElement('br'));
    var articleTxt = widget.createElement('a');
    articleTxt.className = 'myFeed_title';
    articleTxt.href = MyFeed.feed.list[i].url;
    articleTxt.target = '_blank';
    articleTxt.innerHTML = MyFeed.feed.list[i].entry_title;
    li.appendChild(articleTxt);
    li.appendChild(widget.createElement('br'));
    var categoriesTxt = widget.createElement('span');
    categoriesTxt.className = 'myFeed_categories';
    for(var j=0;j&lt;MyFeed.feed.list[i].entry_cats.length;j++) {
      var categoryTxt = widget.createElement('span');
      categoryTxt.className = 'myFeed_category';
      categoryTxt.innerHTML = MyFeed.feed.list[i].entry_cats[j];
      categoriesTxt.appendChild(categoryTxt);
      if(j+1 == MyFeed.feed.list[i].entry_cats.length) {
        break;
      }
      categoriesTxt.innerHTML += ', ';
    }
    li.appendChild(categoriesTxt);
    feedList.appendChild(li);
  }
  widget.setBody(feedList);
}

MyFeed.getWhen = function(datestr) {
  var then = parseInt(datestr);
  var now = Date.parse(Date());
  var whentxt = "";
  var when = now - then;
  if(when &lt; 3600000) {
    whentxt = ""+Math.floor(when/60000)+" minut temu";
  } else if (when &lt; 86400000) {
    whentxt = ""+Math.floor(when/3600000)+" godzin temu";
  } else {
    whentxt = ""+Math.floor(when/86400000)+" dni temu";
  }
  return whentxt;
}

widget.onLoad = function() {
  var url = 'myfeed.php';
  UWA.Data.getJson(url, MyFeed.parseFeeds);
}
&lt;/script&gt;</pre>
<p>Widget ten wysyła zapytanie do specjalnie utworzonego skryptu PHP, który sam pobiera dane z kanałów i na ich podstawie generuje odpowiedź w formacie JSON, którą odsyła do aplikacji. Następnie metoda parseFeeds ze zwróconego JSONa (w specjalnie utworzonym formacie, nie tym zwracanym przez metodę getFeed – oto dowód, że w formacie JSON można przesyłać naprawdę dowolne dane, nie tylko te kompatybilne z uniwersalnym formatem kanałów RSS i podobnych).</p>
<p>Oto zawartość pliku <strong>myfeed.php</strong>:</p>
<pre class="prettyprint">&lt;?php
error_reporting(E_ALL);
header ("Content-type: text/plain");

if(!file_exists("myfeed.txt"))
  echo "";
else {
  $file = fopen("myfeed.txt","r");
  echo " { \"list\" : ";
  $ec=0;
  while(!feof($file)) {
    if($ec == 0)
      echo " [ ";
    else
      echo " , ";
    $ec++;

    $url = chop(fgets($file));
    $xmlDoc = new DOMDocument();
    $xmlDoc-&gt;load($url);

    //get elements from "&lt;feed&gt;"
    $feed=$xmlDoc-&gt;getElementsByTagName('feed')-&gt;item(0);
    $feed_title = $feed-&gt;getElementsByTagName('title')-&gt;item(0)-&gt;nodeValue;
    $feed_url = $url;
    $feed_author = $feed-&gt;getElementsByTagName('author')-&gt;item(0)-&gt;firstChild-&gt;nodeValue;

    //get and output first "&lt;item&gt;" element
    $feed_entry=$xmlDoc-&gt;getElementsByTagName('entry')-&gt;item(0);
    $feed_entry_when = strtotime($feed_entry-&gt;getElementsByTagName('published')-&gt;item(0)-&gt;nodeValue)*1000;
    $feed_entry_cats = $feed_entry-&gt;getElementsByTagName('category');
    $feed_entry_categories = array();

    //get post categories
    for($i=0; $i&lt;$feed_entry_cats-&gt;length; $i++) {
      $feed_entry_categories[] = $feed_entry_cats-&gt;item($i)-&gt;attributes-&gt;getNamedItem('term')-&gt;nodeValue;
    }
    $feed_entry_title = $feed_entry-&gt;getElementsByTagName('title')-&gt;item(0)-&gt;nodeValue;

    echo " { \n";
    echo "\"title\" : \"" . str_replace("\"","\\\"",$feed_title) . "\" , \n";
    echo "\"author\" : \"" . $feed_author . "\" , \n";
    echo "\"url\" : \"" . $feed_url . "\" , \n";
    echo "\"entry_when\" : \"" . $feed_entry_when . "\" , \n";
    echo "\"entry_title\" : \"" . str_replace("\"","\\\"",$feed_entry_title) . "\" , \n";
    echo "\"entry_cats\" : ";
    for($i=0; $i&lt;count($feed_entry_categories); $i++) {
      if($i==0)
        echo " [ ";
      else
         echo " , ";
      echo "\"" . $feed_entry_categories[$i] . "\"";
    }
    echo " ] \n";
    echo " } \n";
  }
  echo " ] }";
}
fclose($file);
?&gt;</pre>
<p>Plik <strong>myfeed.txt</strong>, z którego powyższ skrypt czyta adresy kanałów Atom zawiera po prostu kilka adresów kanałów z kilku zaprzyjaźnionych blogów w serwisie Blogger.com.</p>
<h2>Przydatność do spożycia</h2>
<p>UWA jest wynalazkiem bardzo nowym, wciąż jeszcze rozwijanym i nie w pełni kompatybilnym z wszystkimi tymi platformami, którymi przechwalają się twórcy. Nie mniej jednak wyraźnie widać jego zalety i możliwości. Nie miałem możliwości przetestować jego działania pod Vistą czy MAC OSem ani na iPhone, a testy pod Operą zakończone były porażką, ale w głównych zastosowaniach – na stronach NetVibes, iGoogle czy w ramce iframe na dowolnej innej stronie – sprawdzają się bardzo dobrze. Myślę, że gdy zostanie dopracowane i przeniesione na jeszcze większą liczbę platform (telefony i urządzenia mobilne inne niż iPhone), Universal Widget API może cieszyć się zasłużonym zainteresowaniem, a programy w nim napisane mogą być w równym stopniu proste, jak przydatne.</p>
]]></content:encoded>
			<wfw:commentRss>http://j2ee.pl/2008/08/18/widgety-czesc-pierwsza-universal-widget-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
