Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Aktualizace výpisu na stránce pomocí Rx

15.55 - 24. března 2010 | Webdesign

Včera jsem začal implementovat aktualizaci času na výpisu typu friend feed. Dnes se podíváme na to, jak si zjednodušit práci s asynchronním voláním na server. Samozřejmě opět s využitím jQuery a Reactive Extensions.

Asynchronní volání

Asynchronní volání je z pohledu šetření zdroji výhodné, ovšem z hlediska psaní a údržby kódu už to taková sláva není. Proto nám na pomoc přicházejí Rx, které asynchronní operace převádějí na neblokující lineární kód.

Pojďme hned k dnešní ukázce, která bude o dost jednodušší než včera. Ale použitá technika a principy zůstávají stejné:

Rx.Observable.
  Interval(60000).
  Select(getFeedUpdates).
  Switch().
  SelectMany(function(result) {
    return $(result).find('.hentry').toArray().reverse().toObservable();
  }).
  Subscribe(function(entry) {
    var feed = $('.hfeed')
    feed.prepend(entry);
    $('.hentry:last', feed).remove();
  });

Opět vytvářím Observable objekt, který něco vystřelí jednou za minutu. Tajemství funkce getFeedUpdates si nechám na později. A rovnou se vrhnu na zpracování dorazivších výsledků. Výsledkem mého asynchronního volání je kus HTML kódu s vygenerovaným feedem s novými příspěvky. Z tohohle kusu HTML si vyberu jen elementy s třídou hentry. Ty jsou seřazeny podle data sestupně, ale já chci feed aktualizovat postupně od nejstarších příspěvků k nejnovějším, takže je otočím funkcí reverse a pošlu je do světa jako Observable objekty.

Nakonec se přihlásím k odběru těchto jednotlivých příspěvků pomocí operátoru Subscribe. Když mi nějaký příspěvek přilítne, tak ho vezmu a dám ho na začátek feedu a potom odeberu poslední záznam, aby se nám feed na stránce nenatahoval. Takže jsme elegantně zvládli příjem nových příspěvků. A jak je vlastně načítáme?

function getLastActivityDate() {
  return $('.hfeed>.hentry .updated .value-title').first().attr('title');
}

function getFeedUpdates() {
  var subject = new Rx.AsyncSubject();
  var data = { lastActivity: getLastActivityDate() };

  jQuery.post("url", data, function(result, status) {
    if (status == "success") {
      subject.OnNext(result);
      subject.OnCompleted();
    }
    else {
      subject.OnError(result);
    }
  });

  return subject.AsObservable();
}

Funkce getLastActivityDate načte datum posledního zobrazeného příspěvku, které slouží k načtení novějších příspěvků ze serveru. Opět k tomu využívám mikroformátu hAtom a jeho konkrétní implementaci v mé stránce.

Podívejme se ale raději na další funkci. To je výše zmiňovaná getFeedUpdates, která nám transformuje asynchronní volání na objekt Observable a to pomocí třídy AsyncSubject. Povšimněte si, že v callbacku asynchronního volání vrátím přes closure data do subjektu, který už je tou dobou pozorován první ukázkou kódu.

Když přijde odpověď od serveru, je zavolána metoda OnNext, která vyhodí přijatá data dál ke zpracování. A vzhledem k tomu, že na jeden dotaz asi více odpovědí nepřijde, tak taky ukončíme vysílání výsledků pomocí metody OnComplete. Kdyby náhodou něco na serveru selhalo, máme tu ještě metodu OnError, jejíž zpracování nikde neřeším. :)

Ale vězte, že chyby můžete zpracovávat stejně snadno jako normální data.

No a to je pro dnešek vše. Tuhle ukázku si bohužel vyzkoušet nemůžete, protože k ní už je zapotřebí i serverová část a ta ještě není venku. Příště se možná podíváme, jak pomocí Rx snadno a rychle vytvořit poměrně sofistikovaný našeptávač.

Časový výpis s aktualizací

15.58 - 23. března 2010 | Webdesign

Na Facebooku se mi líbí, že se automaticky aktualizuje čas, před jakým byl příspěvek na zeď pověšen. Jak si naimplementovat vlastní pomocí mikroformátu, jQuery a Rx?

Na Tropu máme několik výpisů typu friend feed, které jsou velice podobné výpisu na zdi na Facebooku. Rozdíl je v tom, že se u příspěvků neaktualizuje doba, před kterou byl příspěvek přidán, a ani se asynchronně nenačítají příspěvky nové. Jak vyřešit první problém, se podíváme dnes.

Reactive Extensions

Již nějakou dobu používám na .netu Rx, která přidává další monady pro interaktivní programování nad IEnumerable<T>, podporu paralelního zpracování a zcela nové reaktivní programování postavené nad IObservable<T>. Vysvětlovat tu dualitu IEnumerable<T> a IObservable<T> dnes hodlat nehodlám. Dodám snad jen to, že tyto extenze jsou již dostupné i pro JavaScript a stáhnout si je můžete na MSDN. K čemu je to dobré?

Reaktivní extenze vám pomohou s řešením ne zrovna snadných úloh, jako je práce s událostmi od uživatele, asynchronní volání služeb a práce s kolekcemi. To vše pomocí standardních LINQ operátorů. Tedy snadno a rychle. Doufám, že si ještě někdy najdu čas a popsal bych je trochu blíž. Možná po implementaci druhé části výše nastoleného problému. :)

Pojďme na věc

jQuery a mikroformáty asi přibližovat nemusím, to jsou věci, které tu už s námi nějaký pátek jsou. Já se na Tropu snažím mikroformáty využít všude kde to jen jde, jak jsem již psal, je to můj datový model stránky. U výpisu typu friend feed je aktuálně nefunkční kostra mikroformátu hAtom. Takže to pojďme napravit a rychle jí zprovoznit. Vezmu kus kódu a upravím ho tak, aby to byl platný hAtom:

<li class="hentry" id="activity-2330">
  <p class="entry-title"><a class="vcard author" href="/lide/zbiejczuk">
    <span class="admin" title="Trop Administrator">
     <span class="power" title="Znalec">
      <span class="fn">zbiejczuk</span>
     </span>
    </span></a>
    napsal recenzi pro <a href="/mista/808/ku-bar-praha#review-1096" rel="Bookmark">K.U. Bar</a></p>
  <p class="entry-content">
Hoďte na sebe nevyzývavě značkové oblečení, kupte si drahý cigára,
popíjejte koktejly a konverzujte markeťáckým…
  </p>
  <p class="meta">přidáno
    <span class="updated">
     <span class="text">22. března 2010 ve 12.24</span>
     <span class="value-title" title="2010-03-22T11:24:19Z"></span>
    </span>
  </p>
</li>

Další soustředění budu směřovat na span se třídou updated, protože tam se skrývá ta důležitá věc – čas. Čas, kdy byl příspěvek publikován. Tento čas vezmeme a převedeme ho na „hezčí“ textovou prezentaci. Strojově získatelná data dle ISO8601 máme uložena pomocí value-class-patternu, pro snažší update je tu navíc span s třídou text, kam budeme strkat náš vlastní text. Parsování mikroformátu provádím pomocí jQuery.

Rx jsou psány tak, aby s jQuery mohly fungovat, ale já jsem mlsná huba a trošku si jQuery osolím, aby se mi s ním a Rx pracovalo trochu líp:

jQuery.fn.toObservable = function (eventType, eventData) {
  if (arguments.length == 0) {
    return Rx.Observable.FromArray(this.toArray());
  }
  return Rx.Observable.FromJQuery(this, eventType, eventData);
}

Pokud zavolám toObservable nad jQuery objektem bez parametrů, převede se výsledek dotazu na pole (nalezených elementů) a to je převedeno na Observable objekt se kterým už pracují samotné Rx. Pokud zadám jako parametr název jQuery události, je vrácen Observable objekt nad těmito událostmi. To ale dnes nevyužiju, ale i tak se může hodit. Ještě by to šlo rozšířit o podporu live událostí, snad jindy.

Dále už se vrhnu rovnou do rozbouřené vody. jQuery na mne začne chrlit nalezené elementy, které musím zkrotit! Jak, kdy, proč? No tak, že mu to řeknu:

Rx.Observable.
  Interval(10000).
  Select(function () {
    return $('.hentry .updated').toObservable();
  }).
  Switch().
  Select(mapToElementValuePair).
  Subscribe(changeElementText);

Nejprve si vytvořim Observable objekt, který na mne jednou za 10 s vyplivne sadu nalezených elementů, které jsou součástí mikroformátu a nesou informaci o čase. Swicht slouží k tomu, že pokud by se nestihli v daném intervalu zpracovat všechny elementy, nezačne chrlit další. Tyhle elementy pak vezmu (druhý Select) a vytvořím si pomocný objekt, který obsahuje element a vyparsovaný objekt Date s časem, který element v sobě nese. Tohle je vše lenivě vyhodnocováno, takže stále nemám vůbec nic. :) To až pomocí metody Subscribe se pověsím na příjem a čekám, až mi nějaký element (v tomto případě už obalový objekt) přilítne. Pak ten element vezmu, datum převedu na text typu před 5 minutami a aktualizuju element se třídou text. A je hotovo. :)

Kompletní ukázku kódu najdete na gitu. Ona se trošku liší a je malinko obšírnější, ale pro její pochopení, jsem tu snad naznačil dost. :) Enjoy!

Facebook Connect na Trop.cz

20.00 - 1. února 2010 | Webdesign

Po delší době přicházíme s dalším buildem Tropu, který je tentokrát ve znamení Facebook Connect. Od dnešního dne se můžete na Trop.cz přihlašovat pomocí vašeho Facebook účtu. Facebook se tak zařadil mezi Seznam, Google, Twitter a další OpenId poskytovatele přihlašování, kteří už na Tropu jsou.

Facebook Connect

Stávající uživatelé

Stávající uživatelé si mohou svůj účet propojit s Facebookem v editaci profilu. Jak na to, se můžete podívat v následujícím krátkém videu: Jak propojit účet s Facebookem.

Můžete si všimnout, že jsem potvrzoval práva na publikování. To proto, že Trop nyní umí posílat vaše recenze na zeď. Pokud při propojování s facebookem potvrdíte publikování, budou se vaše nové recenze posílat i na Facebook. Nemusíte psát, že se vám někde líbilo/nelíbilo dvakrát, stačí to napsat na Trop a vaši přátelé se o tom dozvědí.

Noví uživatelé

Noví, ještě neregistrovaní uživatelé mají nyní další možnost, jak se snadno na trop zaregistrovat a nezatěžovat se s vyplňováním profilu. Vše potřebné se vyplní z Facebooku.

Recenze

Dalších změn se dočkaly recenze. Nyní konečně můžete vaši recenzi zpětně upravit včetně tagů a rozšířených hodnocení. Textové pole pro editaci je nyní větší a úprava je mnohem pohodlnější. Další z novinek je hodnocení recenzí. Pokud se vám něčí recenze líbí, můžete jí posunout nahoru svým hlasem. Samozřejmě můžete poslat dolu i recenze, které nemají žádnou užitnou hodnotu. Každý registrovaný uživatel má právo jednou zahlasovat k recenzi někoho druhého.

Tlačítka pro editaci a hlasování najdete v pravém horním rohu po najetí na recenzi.

Twitter

Ode dneška můžete sledovat, co se o Tropu štěbetá na Twitteru. Na domovské stránce máme nyní widget s Twitterem. Podobně přibyl widget s Twitterem na profilové stránky uživatelů, kteří mají svůj Twitter spojený s Tropem. Můžete tam snadno vidět, čím se tropáci zabývají i mimo psaní zajímavých recenzí. :) Pokud chcete vědět, co štěbetá Trop, můžete ho sledovat také. Najdete zde mimo jiné i seriál tipů na zajímavá místa.

Přání a oprava bugů

Snažili jsme se splnit vaše přání, která nám můžete posílat (a posíláte) na náš uservoice. Některé z nich jsem již zmínil výše, mezi dalšími je oprava hledání, nyní opět můžete hledat i mimo Prahu. Byl vylepšen způsob jakým se posílají chybové stránky, nyní už by měly být jednotné a brzy i o něco použitelnější.

Spustili jsme Trop blog

16.22 - 17. prosince 2009 | Gryphoon

Už je tomu tak, každá správná sociální služba se má šířit všema kanálama a dnes přibyl další.

Dneska najdete Trop skoro všude:

Původně jsem chtěl blog nasadit na některý z existujících redakčních systémů. Výbíral jsem z Wordpressu, Oxite, AtomSite a nakonec nevybral ani jeden. :) Instalovat na server další databázový stroj (MySQL) jen kvůli blogu mi přišlo zbytečné – Wordpress padl. Oxite se zdá být zajímavým, protože na něm jsou postaveny prezentační weby Microsoftích konferencí a navíc je to napsaný v ASP.NET MVC (stejně jako Trop). Bohužel je to celé dost nepoužitelné a navíc chybí podpora pro správu uživatelů. Což je velký problém, kterým trpí i jinak zajímavě vypadající AtomSite.

Velké ostřílené distribuce jako SubText, BlogEngine.net nebo dasBlog se mi už zkoušet nechtělo a sáhl jsem po tom s čím dokážu dělat snadno a rychle. Ano, po stařičkém Gryphoonovi, který pohání i tento blog. Chtělo to jen pár drobných úprav a frontend, který byl jen a pouze na tomto blogu, už je nasaditelný i na jiné domény než rarouš.net. :) Možná ho o prázdninách dám nějak do kupky a vydám bastl hybrid Gryphoon 1.90. :)

Stay tuned.

Tropněte si o sud piva

15.12 - 20. listopadu 2009 | Webdesign

Na Tropu už máme přes šestset recenzí a to díky vám! Za poslední týden se počet recenzí takřka zdvojnásobil. To mě velice těší, protože Trop tak začíná mít smysl. Líbí se mi, že začali psát i další lidé a hlavně kvalitní recenze. Moc se mi líbí recenze od Dera, jsou snad ještě lepší, než jeho titulky na HIMYM. ;) Za zmínku stojí také recenze slovodaloslovo, což je profesionální copywriterka. :) Napsala o nás taky jeden spot. Děkujeme.

Každý má svůj osobitý styl a to je super. Jen tak dál! :)

Proč psát na Trop?

Možná si říkáte, „proč bych na Trop měl psát?“ Jedním z důvodů může být to, že se procvičíte v psaní jako takovém. Navíc tim můžete někomu pomoci se rozhodnout, zda má cenu neznámé místo navštívit. A v neposlední řadě probíhá soutěž! Máte ještě deset dní na to se umístit na čelních pozicích a vyhrát některou z cen. Osobně pochybuju o tom, že ještě někdo dokáže dohnat voytu, který žebříček táhne a jde si pro svůj sud piva, ale nemožné to je! Třeba mu ten sud ještě někdo vyfoukne. ;)

Takže Tropujte!

Související

Mikroformáty jako datový model stránky

12.47 - 18. listopadu 2009 | Webdesign

Dříve, když jsem psal webové aplikace, kde bylo potřeba hodně JavaScriptu, aby se dosáhlo pohodlné práce, duplikoval jsem data. Ano, je to tak a stydím se za to. Většina dat, které se na stránce vypisovaly, byla duplicitní. Jednou byly v HTML a podruhé v JSON, aby se s nimi dalo snadno pracovat v JavaScriptu. Jenže všichni víme, že duplikování je zlo. :)

Tropu jsem se tomuto nešvaru snažil vyhnout. A tak je většina dat ve stránkách označena mikroformáty. Výhodou mikroformátů je, že jsou snadno strojově zpracovatené. Tudíž i JavaScriptem. Pokud se třeba podíváte na detail místa (např. The Pub na Staroměstské) uvidíte mapku, kde je bublina s kontaktními údaji místa. Tato data nejsou v žádném JSON ve stránce, ani se nestahují AJAXovým dotazem. Script jednoduše vezme data z mikroformátu hCard včetně geo souřadnic, kde se má bublina vykreslit.

Podobný model je aplikován na různých místech Tropu.

Mikroformáty vs. RDFa

Myslím, že v tomto případě se i ukazuje, že mikroformáty jsou lepší než RDFa. Protože parsovat mikroformáty pomocí jQuery je mnohem snažší a přehlednější. RDFa je možná flexibilnější v tom, kolik gramatik dokáže pojmout, ale to je i jeho zásadní slabinou. Mikroformáty definují jednoduché formáty, které staví na jednoduchém modelu HTML. Existují nástroje, díky nimž lze s nimi snadno pracovat.

Mikroformáty a ASP.NET MVC

Úžasnou novinkou ASP.NET MVC 2 bude extenze Html.DisplayFor, kde se vytvoří jediná šablona třeba s vizitkou uživatele a pak jí mužu používat všude, aniž bych někde na něco zapomněl nebo něco nabořil. Dnes musím mít několik extenzí pro různé typy dat, kde mám navíc kód přímo v extenzi. Sice je jednoduchý, ale čím méně HTML v C# kódu, tím lépe. (On to tedy není přímo HTML kód, ale jeho objektová reprezentace.)

Práce s mikroformáty tak bude mnohem jednodušší a ucelenější. :)

Odpalování akcí měnících data odkazem

09.29 - 16. listopadu 2009 | Webdesign

V RESTové architektuře webu byste neměli odpalovat akce, které mění data, pomocí odkazů. Měli byste tak činit pomocí sloves HTTP protokolu (PUT, POST, DELETE). Přejdu fakt, že dnešní prohlížeče znají jen sloveso POST a ostatní musíte simulovat pomocí XHR. Stejně se dostanete do situací, kdy potřebujete nějakou akci měnící data odpalít odkazem.

Abych pro příklad nemusel chodit daleko, vezmu si hlasování k akcím na Tropu. U každé akce se můžete vyjádřit k tomu, zda na akci půjdete, možná se ukážete nebo nepůjdete. Pokud je uživatel nepřihlášený, vidí pod názvem akce tři ikonky s počtem hlasů. Po přihlášení se stanou aktivními a lze s nimi hlasovat. Původně byla tato „tlačítka“ pouhými odkazy na akci, která hlasování zpracovávala. Jenže po tom, co jsem pouštěl některé spidery, začaly přibývat hlasy.

Tím se dostáváme k praktickému důsledku porušení doporučení z prvního odstavce. Problém jsem nakonec vyřešil následujícím vzorem: Do stránky jsem přidal formuláře, které bezpečným způsobem odpalují akce měnící data. Každý formulář má své id. Odkazy, které původně vedly na akce měnící data, nyní odkazují na id jednotlivých formulářů a mají třídu form-submit. Jednoduchý jQuery kód pak projde tyto odkazy a na click jim naváže submit odkazovaného formuláře a ten pak schová.

Stránka vypadá pořád stejně, chová se stejně, ale dělá to jinak. Pokud nemá uživatel povolený JavaScript, tak se po kliknutí na ikonku dostane na správný formulář, který musí odeslat stiskem tlačítka submit. Funkčnost tak zůstává přístupná i bez JavaScriptu. Zároveň nehrozí, že by došlo k nechtěné aktivaci akce nějakým spiderem, který si ošahává odkazy na stránce.

Snad se bude hodit i vám.

Seznamte se s Tropem

14.29 - 13. listopadu 2009 | Webdesign

Pomalu do světa pouštíme naši novou službu – Trop. O co vlastně jde? Je to sociální platforma pro snadnou výměnu zkušeností z různých míst. Začínáme s tím, co je nám nejbližší. Začínáme v Praze a to s hospodami, restauracemi a kluby. :)

Zatím jsme pořád v betě, protože každou chvíli něco rozbiju, nebo pokazim, ale snažíme se chyby vychytávat a rychle opravovat. Technologicky to je celé postavené na kombu ASP.NET MVC, NHibernate, Castle Windsor, MS SQL 2008 a IIS7. O některých věcech, které mě potkaly už jsem psal (MVC, Binsor), jiným se chci věnovat v budoucnu.

Kolik účtů máš, tolikrát jsi otrokem

Vím, že někteří z vás tam již účet mají, a tak to pro ně není žádným překvapením. Ti, co ještě účet na Tropu nemají, mají hned několik možností, jak si ho vytvořit. Nechcem po vás žádné složité vyplňování registrace. Asi nejjednodušší je využít možnosti přihlášení pomocí Twitteru (OAuth), kdy se vám automaticky vytvoří profil dle vašich údajů na Twitteru, pěkně i s vaší profilovou fotkou. Pak už můžete normálně Trop používat. Podobně funguje i vytváření účtu pomocí OpenId.

V blízké době se objeví i možnost přihlašování pomocí Facebook Connect. S touto novinkou přibude i jednodušší správa napojených účtů a možnost publikace vašich recenzí na Twitter a Facebook. (Dnes můžete sdílet místa a akce).

Místa blízká i vzdálená

Teď, když už u nás máte účet, tak můžete napsat nějakou recenzi na vaše oblíbené či neoblíbené místo. Využijte našeho hledání! Pokud už vaše místo někdo zadal, mělo by být ve výsledcích hledání. Pak stačí kliknout na tlačítko Napiš recenzi a začít psát. Nezapomeňte zadat vaše hodnocení! :) Pokud chcete, aby vaše recenze byly více sexy, zkuste psát s Texy! Pokud místo nalezeno nebylo, tak ho prostě přidejte. :)

Akce

Jedna z věcí, která mi na internetu chyběla, bylo řešení následujícího scénáře: Chceme se sejít s kámošema v nějaký hospodě. První věc, je vybrat správnou hospodu. Většinou je to nějaká, kterou známe, někteří však třeba ještě ne. Tak místo máme, pokusíme se najít jeho stránky, abychom mohli udělat rezervaci a ti, co to tam ještě neznají, aby se podívali. Pak je tu další krok, poslat místo neznalým na mapě, aby tam trefili a ještě raději všechny obeslat e-mailem s ical v příloze, aby nezapomněli.

Takový mail obsahuje spoustu odkazů. :) Kdo je bude proklikávat? No však víme, takže budete řešit ještě deset telefonů, kvuli datu a pak navigaci na místo. Teď když mám Trop, tak většinu věcí najdu na jednom místě. Některé věci ještě sice nejsou dotažené do podoby, jakou bych si představoval, ale věřím, že brzy přibudou. A pak bude organizace větší sešlosti hračkou. :)

Zkoušejte

Tak zkoušejte, zkoušejte. Dejtě vědět, jak se líbí, nebo co případně vylepšit. Nejlepší cestou jak přijít s nápadem je naše user voice forum, kde můžete zadávat vaše nápady a hlasovat pro jiné, které se vám líbí. Samozřejmě hlašte i chybky, ale snad už jich moc neni.

Pokud chcete sledovat, co se na Tropu děje, můžete na FriendFeedu, Twitteru nebo na Facebooku. A nebo taky tady.