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

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.

Vlastní serverové ovládací prvky v ASP.NET MVC

10.32 - 29. března 2009 | Webdesign

Motto: foreach je fajn na prototypování, ale většinou mu za chvíli dojde dech a svádí k zanášení příliš logiky do kódu šablony. A to je špatně.

Už jsem se zmiňoval o tom, že v ASP.NET MVC lze užívat serverové ovládací prvky, takže je využijeme k zapouzdření složitější zobrazovací logiky.

Motivace

Jednou z hlavních nevýhod, kterou jsem viděl na MVC, byl přístup ke skládání šablon. Jednotlivé kusy šablony jsou rozházeny v MasterPage, ViewPage (aspx) a ViewUserControlech (ascx). V Atlasu jsme razili teorii, že šablona by měla být pokud možno co nejcelistvější, aby se nemuselo nikde nic hledat a kodér rychle udělal potřebné změny. Proto existovala sada serverových ovládacích prvků, které byly plně šablonovatelné.

Když naběhlo CHEllou, nechápali jsme, jak to může někdo používat. Každičká část šablony byla (v té době, jak je to dnes – nevím) byla rozeseta v hierarchii složek (podle dědičnosti). A to je v podstatě hlavní rozdíl mezi ASP.NET a architekturou MVC. Tedy pokud jste omezeni view enginem, který používáte.

Již nějaký pátek pracuji na web 2.0 aplikaci, která je postavená mj. na ASP.NET MVC. Měl jsem tedy možnost vyzkoušet hodně možných postupů: od logiky v šabloně, přes HTML helpery, RenderPartial a RenderAction až po vlastní serverové ovládací prvky. A ty nakonec vítězí na plné čáře! Pojďme se podívat, jak si napsat elegantní serverové ovládací prvky pro ASP.NET MVC.

Evoluce logiky v šabloně

Začínal jsem s nadšením s jednoduchou logikou v kódu, tak jak to vidíte v ukázkách či na prezentacích o ASP.NET MVC. Složitější věci jsem se snažil přesunout do HtmlHelperu pomocí vlastních extenzí. Když jsem pak narazil na helpery, které zanáší do view „lambda hell“, trochu mě zamrazilo. Vyberu jen dva příklady: Philův Code based Repeater for ASP.NET MVC a Jardův Simple MVC controls. Nebojte, podobných programátorských krás najdete povícero. Bohužel, je to nepoužitelné pro kodéra. Navíc jsem zastáncem myšlenky minima kódu v šabloně.

Další věcí, která mě tak trochu děsí, je jakým způsobem se předvádí generování HTML formuláře.

<% using(Html.BeginForm("Send", "Comments")) { %>
  <!-- prvky formuláře -->
<% } %>

Je to krásná ukázka užití vzoru IDisposable, ale do šablony nepatří. Helpery uživát jen jako dobré koření – po špetkách.

<form action='<%= Url.Action("Send", "Comments")) %>' method="post">
  <!-- prvky formuláře -->
</form>

Myslím, že takovýto zápis je mnohem srozumitelnější a přitom dělá to samé. Jako bonus můžete ve vašem HTML editoru využívat scope collapsing. Vhodnější by ještě bylo použít helper Url.RouteUrl, který hledá routy podle klíče a tudíž je o dost výkonnější (pokud máte definováno více rout).

Opusťme teď formulář a pokročme k vypisování dat.

Prvním způsobem, jak vypisovat data, je foreach. Je silně typový, což považuju za obrovskou výhodu, a nepřináší overhead v podobě instanciování tříd a parsování šablon serverových ovládacích prvků.

<ul>
<% foreach (var user in Model.Users) { %>
<li><%= user.Name %></li>
<% } %>
</ul>

Tím však jeho možnosti končí. Pokud potřebujeme např. odlišit každou druhou položku, nebo vypsat něco jiného, pokud nejsou žádná data, musíme kód znepřehledňovat, nebo zvolit jiné řešení. Philův repeater už jsem zmiňoval. Další možností je využít asp:Repeater nebo mvc:Repeater. Ani jeden mi nevyhovuje. První se musí nějak nalít daty a pak s nimi svázat (nutnost codebehind nebo script runat=server), druhý zase pracuje s ViewData slovníkem a evalováním. Takže nezbývá než si napsat vlastní.

Silně typový repeater v ASP.NET MVC

Základem je jednoduchá myšlenka. Použít MvcControl z futures a view model opatřit kontrakty.

public interface IHaveUsers {
  IEnumerable<User> Users { get; }
}

public class UsersListViewData : IHaveUsers {
  public IEnumerable<User> Users { get; set; }
  // další vlastnosti view modelu
}

Zavedli jsme si view model třídu, která se nejspíš bude posílat na pohled Index řadičem UsersController. Možná. Každopádně jsme si zavedli jednoduchou abstrakci a možnost znovupoužití v podobě rozhranní IHaveUsers. Snad můžeme dál.

using Microsoft.Web.Mvc;
using Rarous.Web.UI;

[ParseChildren(true)]
public partial class UsersRepeater : MvcControl, ILayoutTemplateable {

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(IGenericContainer<User>))]
  [TemplateInstance(TemplateInstance.Multiple)]
  public ITemplate ItemTemplate { get; set; }

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(IGenericContainer<User>))]
  [TemplateInstance(TemplateInstance.Multiple)]
  public ITemplate AlternatingItemTemplate { get; set; }

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(INamingContainer))]
  [TemplateInstance(TemplateInstance.Multiple)]
  public ITemplate SeparatorTemplate { get; set; }

  public string LayoutContainerId { get; set; }

  [DefaultValue(typeof(ITemplate), "")]
  [PersistenceMode(PersistenceMode.InnerProperty)]
  [TemplateContainer(typeof(INamingContainer))]
  [TemplateInstance(TemplateInstance.Single)]
  public ITemplate LayoutTemplate { get; set; }
}

Podědili jsme si MvcControl, který mimo jiné zpřístupňuje ViewData, a implementovali nějaké šablony.

public partial class UsersRepeater {
  private class UsersViewDataFetcher {
    public IEnumerable<User> GetUsers(object model) {
      var result = model as IHaveUsers;
      if (result != null) {
        return result.Users;
      }
      return null;
    }
  }
}

Jednoduchý helper pro získávání dat z modelu. Zkouší využít kontraktu IHaveUsers, který jsme si zavedli výše, k získání dat z modelu. Zde je místo pro budoucí rozšíření o další možné zdroje. Pokud nic nenajdeme, vrátíme null.

public partial class UsersRepeater {
  protected override void OnPreRender(EventArgs e) {
    base.OnPreRender(e);

    var fetcher = new UsersViewDataFetcher(ViewData.Model);
    var users = fetcher.GetUsers();
    if (users == null) {
      return; // nebo verenderovat NoDataTemplete
    }

    Controls.Clear();

    Control layoutContainer = TemplatingHelper.CreateLayoutContainer(this, this) ?? this;

    var iterator = new ItemsIterator<User>(users);
    foreach (var user in iterator.Iterate()) {
      if (iterator.IsFirst == false) {
        TemplatingHelper.Instantiate(new EmptyContainer(), SeparatorTemplate, layoutContainer);
      }
      ITemplate template = iterator.IsAlternate ? AlternatingItemTemplate ?? ItemTemplate : ItemTemplate;
      TemplatingHelper.Instantiate(new GenericContainer<User>(user), template, layoutContainer);
    }

    layoutContainer.DataBind();
  }
}

Nakonec přepíšeme metodu OnPreRender, ve které získaná data proměníme pomocí šablon na výstupní kód. Používám zde spoustu věcí, které jsem použil již dříve. Jedinou novinkou je třída ItemsIterator, která zaobaluje logiku, pro zjišťování, zda jde o první prvek, alternativní prvek a počítá aktuální index prvku.

public class ItemsIterator<T> {

  private readonly IEnumerable<T> _items;

  public ItemsIterator(IEnumerable<T> items)
    : this(items, 0) {
  }

  public ItemsIterator(IEnumerable<T> items, int firstIndex) {
    _items = items;
    IsFirst = true;
    IsAlternate = false;
    CurrentIndex = firstIndex;
  }

  public bool IsFirst { get; private set; }
  public bool IsAlternate { get; private set; }
  public int CurrentIndex { get; private set; }

  public IEnumerable<T> Iterate() {
    foreach (var item in _items) {
      yield return item;
      IsFirst = false;
      IsAlternate = !IsAlternate;
      CurrentIndex++;
    }
  }
}

Jednoduchá věcička, která je určená k eliminaci otrocky opakovaného kódu.

Užití takového repeateru je pak jednoduché:

<rarous:UsersRepeater runat="server" LayoutContainerId="UsersPlaceHolder">
  <LayoutTemplate>
    <ul>
      <asp:PlaceHolder ID="UsersPlaceHolder" runat="server"/>
    </ul>
  </LayoutTemplate>
  <ItemTemplate>
    <li><%# Container.DataItem.Name %></li>
  </ItemTmplate>
</rarous:UsersRepeater>

Závěr

Snažil jsem se sdělit svůj názor, že v šablonách by mělo být jen tolik programového kódu, kolik je nezbytně nutné. Zároveň se držet zásady jediné zodpovědnosti tříd a znuvupoužitelnosti s využitím generického pomocníka pro iteraci a kontraktů ve view modelu. Zároveň maximálně využít kód, který jsem už psal v předchozích spotech. Je možné, že jsem nepoužil dostatečně kvalitní názvy tříd nebo metod, připomínky klidně piště i k nim.

Zdroje o ASP.NET MVC pro začátečníky

18.51 - 11. března 2009 | Webdesign

Možná hledáte nějaký materiál, který vám pomůže začít s ASP.NET MVC. Pojďme se podívat, jaké máte možnosti.

Knihy

Asi nejčastějšími studijními materiály jsou knihy. Protože je ASP.NET MVC ještě hodně mladý framework, který ještě nebyl oficiálně vydán (produkční verze), žádná kniha ještě nevyšla. Ale minimálně na dvou se usilovně již několik měsíců pracuje. Ještě lepší zprávou je, že jejich rozpracované verze jsou už nyní k dispozici!

Za první knihou ASP.NET MVC Framework Unleashed stojí Senior Program Manager ASP.NET MVC a autor jedné z nejprodávanějších knih o ASP.NET  – Stephen Walther. Jednotlivé kapitoly publikuje na svém blogu. Ty budou po jejím dokončení z blogu staženy. Publikovány byly zatím tyto kapitoly:

  1. Chapter 1 – An Introduction to ASP.NET MVC
  2. Chapter 2 – Building a Simple ASP.NET MVC Application
  3. Chapter 3 – Understanding Controllers
  4. Chapter 4 – Understanding Views
  5. Chapter 5 – Understanding Models
  6. Chapter 6 – Understanding HTML Helpers
  7. Chapter 9 – Understanding Routing

Další knihou je Professional ASP.NET MVC 1.0 z rukou pánů Scott Guthrie, Phil Haack, Scott Hanselman a Rob Conery. Pokud nevíte, kdo jsou tito pánové zač, tak byste to měli rychle dohnat. ScottGu je autorem ASP.NET a dnes je vicepresidentem vývojářské divize Microsoftu. Phil je Senior Program Manager ASP.NET MVC, Routingu a integrace dynamických jazyků do ASP.NET. ScottHa byl první, kdo loni na MIXu ASP.NET MVC presentoval a Rob Conery je autorem ukázkové aplikace – a především poučných screencastů z její tvorby – StoreFront, která je postavená na MVC frameworku. Z knihy byla zatím uvolněna první kapitola, která je průvodcem krok za krokem jak začít stavět aplikaci s ASP.NET MVC.

Ukázkové aplikace

Pokud se vám dobře učí čtením zdrojových kódů, není nic lepšího, než si zdrojové kódy ASP.NET MVC stáhnout na CodePlexu. Z nich můžete pochytit ledasco, ale jak s tím dělat aplikace už moc ne. Proto tu jsou ukázkové aplikace. Tou první a asi nejrozsáhlejší je MVC Storefront. Jenže její zdrojáky byly chvíli na CodePlexu, pak je Rob smazal a slibuje, že brzy budou nové – aktuální. Další ukázková aplikace vznikla pro potřeby druhé jmenované knihy a jmenuje se Nerddinner.

Webcasty

Když ještě nejsou k MVC Storefront zdrojáky, tak vězte, že k němu je asi pětadvacet screencastů! Rob zde provádí vývojem e-shopu. Během té doby prozkoumává různá zákoutí webového vývoje, vylepšuje design aplikace, užívá užitečných komponent atd. Rozhodně stojí za zhlédnutí.

Další videa, která vám snad pomohou s MVC frameworkem začít, najdete přímo na stránkách ASP.NET MVC.

Záznamy přednášek

Doporučení hodné jsou záznamy z loňského MIXu a PDC, konkrétně tyto:

  1. Developing ASP.NET Applications Using the Model View Controller Pattern
  2. ASP.NET MVC : A New Framework for Building Web Applications

Na letošním MIX, který bude již příští týden, bude asi 5 přednášek věnovaných ASP.NET MVC a očekává se, že tam bude také uvedena jeho finální verze.

Na loňském WebExpu jsem měli s Borkem přednášku o ASP.NET Futures a o MVC jsem také mluvili. Přednáška se natáčela, a pokud bude záznam zveřejněn, tak tam možná najdete pár zajímavých informací. :)

Blogy

Zatím největším zdrojem a zároveň nejroztříštěnějším jsou blogspoty. Nejvíc informací najdete na blozích již výše zmiňovaných pánů. Do jejich společnosti se rád vloudím i se svojí troškou do mlýna, ale troufnu si tvrdit, že v některých už jde o trošičku pokročilejší témata a pro jejich pochopení byste už něco měli mít načteno a nazkoušeno. :)

No koukám, že se mi tady z toho stává pěkná linkfarma, tak to raději ukončím a doufám, že se máte od čeho odrazit…

Implementace tag cloudu

18.53 - 28. února 2009 | Webdesign

Zajímavé je, jak se problematice celkem rozšířené vlastnosti webových aplikací v éře Webu 2.0, kterou tag cloud bezesporu je, věnuje málo prostoru. Protože pracuju na jednom sociálním webu a k implementaci tag cloudu jsem se také dostal, tak se na něj pojďme podívat.

Top-down design

Začneme implementací na výstupu. To je to, co vidí uživatel. Porozhlédněme se nejprve po nějakém vhodném mikroformátu. Na snadě je rel-tag, který slouží k označování odkazů tagu. Když budeme hledat dál, jistě narazíme na hTagCloud. Tento mikroformát je sice ve stádiu návrhu, ale dá se říct, že je použitelný v praxi. Jak vypadá?

hTagCloud

Cloud je vyznačen elementem s třídou hTagCloud. Tento element by měl obsahovat seznam tagů. Seznam můžeme označit třídou, zda jde je seřazen podle abecedy (class="alphabetical") nebo podle popularity (class="popularity"). Popularitu jednotlivých tagů označíme posléze třídou. Základní úroveň popularity vyznačuje třída popular. Oblíbenější tagy mají třídu v-popular. Nejoblíbenější tagy pak třídou vvvv-popular. Můžeme takto tedy odlišit pět úrovní popularity.

Ukázka mikroformátu přímo z wiki autorů:

<div class="hTagCloud">
  <ul class="popularity">
    <li class="vvvv-popular"><a href="/tags/Web+Standards+Group">Web Standards Group</a></li>
    <li class="vvv-popular"><a href="/tags/accessibility">accessibility</a></li>
    <li class="popular"><a href="/tags/beta+tester">beta tester</a></li>
    <li class="vvv-popular"><a href="/tags/css">css</a></li>
    <li class="v-popular"><a href="/tags/ex-coder">ex-coder</a></li>
    <li class="vv-popular"><a href="/tags/usability">usability</a></li>
    <li class="vvvv-popular"><a href="/tags/wsg">wsg</a></li>
  </ul>
</div>

To bychom měli HTML kód, teď ještě nastylovat, aby z toho opravdu cloud byl:

.hTagCloud {text-align:center}
.hTagCloud ul{list-style-type:none;padding:0;margin:0}
.hTagCloud li{display:inline;font:.6875em sans-serif;margin:0;padding:0}
.hTagCloud .v-popular{font-size:1.273em}
.hTagCloud .vv-popular{font-size:1.818em}
.hTagCloud .vvv-popular{font-size:2.545em}
.hTagCloud .vvvv-popular{font-size:3em}

Máme tedy připraveno to, co uvidí uživatelé. Teď ještě potřebujeme logiku, která rozhodne, jak populární tagy vlastně jsou.

Implementace na serveru

Nejprve si vytvoříme třídu reprezentující tag. Ta bude obsahovat text tagu a jeho četnost.

public class Tag {
  public string Text { get; set; }
  public int Count { get; set; }
}

Teď budeme potřebovat vypočítat, jak populární vlastně konkrétní tag je. Tady se dostáváme k poměrně zajímavému problému. Nejprve potřebujeme spočítat váhu tagu v cloudu a tu pak promítnout na pětistupňové škále. Praxí je ověřeno, že hezky cloud vypadá, když se použije logaritmická distribuční funkce. Proto si vytvoříme jednoduchý helper, který nám bude váhu tagu vypočítávat a rovnou nám vrátí CSS třídu vhodnou pro hTagCloud.

using System;
using System.Linq;
using System.Text;

public static class TagCloudExtensions {
  private const int MostPopular = 5;
  private const int MorePopular = 2;
  private const int Popular = 1;

  public static string GetCssClass(this IEnumerable<Tag> tags, Tag tag) {
    int minOccurs = tags.Min(t => t.Count);
    int maxOccurs = tags.Max(t => t.Count);

    int distribution = CountDistribution(tag.Count, minOccurs, maxOccurs);

    return GetCssClass(distribution).ToString();
  }

  private static StringBuilder GetCssClass(int distribution) {
    if (distribution < MorePopular) {
      return new StringBuilder("popular");
    }
    if (distribution == MorePopular) {
      return GetCssClass(--distribution).Insert(0, "v-");
    }
    return GetCssClass(--distribution).Insert(0, "v");
  }

  private static int CountDistribution(int currentOccurences, int minOccurs, int maxOccurs) {
    if (minOccurs < Popular) {
      throw new ArgumentOutOfRangeException("There must be atleast one occurence.");
    }

    double weight = (Math.Log(currentOccurences) - Math.Log(minOccurs))
      / (Math.Log(maxOccurs) - Math.Log(minOccurs));
    int distribution = Popular + (int)Math.Round(weight * (MostPopular - Popular));

    return distribution;
  }
}

Tento helper rozšiřuje kolekci tagů o metodu o metodu, která vrátí CSS třídu pro konkrétní tag. A to je vše. Happy tagging!

Serverové ovládací prvky v ASP.NET MVC

12.32 - 21. února 2009 | Webdesign

Docela často se vyskytující fámou je, že v ASP.NET MVC nelze používat serverové ovládací prvky (Server Controls). Pravda to je jen z části, nelze používat jen ty prvky, které pro svoji funkčnost vyžadují ViewState. Pojďme se podívat na ty, které fungují i v ASP.NET MVC a můžou nám poskytnout nějakou zajímavou funkcionalitu a zpřehlednit tak naše View.

MasterPage a Placeholdery

Snad první komponenty, které použijete, jsou asp:ContentPlaceHolder a asp:Content. Narazíte na ně při definování globální šablony (Master Page) a jednotlivých pohledů (View). Většinou je použijete automaticky a ani si neuvědomíte, že jde o serverové komponenty. A to je dobře. Rozhodně je lepší používat master page než server side include nebo do všech stránek vkládat view user controly se sdílenými částmi šablony.

LoginView a spol.

Další rozhodně doporučitelnou komponentou je asp:LoginView. Ta slouší k rozdílnému zobrazování obsahu pro nepřihlášené/přih­lášené uživatele a také pro jednotlivé uživatelské role. Předpokladem je, že využíváte ASP.NET Membership nebo nějakou vlastní implementaci, která nastavuje do kontextu správné IPrincipal. Pak můžete v kódu použít třeba toto:

<asp:LoginView ID="LoginView1" runat="server">
  <AnonymousTemplate>
    Nepřihlášený | <%= Html.ActionLink("Přihlásit se", "Login", "Account") %>
  </AnonymousTemplate>
  <LoggedInTemplate>
    <asp:LoginName runat="server" />| <%= Html.ActionLink("Odhlásit se", "Logout", "Account") %>
  </LoggedInTemplate>
</asp:LoginView>

Tím docílíte zobrazení odkazu pro přihlášení nepřihlášenému uživateli a odkazu pro odhlášení uživateli přihlášenému. Jak vidíte, je možné používat i asp:LoginName pro výpis jména aktuálně přihlášeného uživatele.

Localize pro lokalizaci

Pokud děláte na webové aplikaci, která má být lokalizovaná do více jazyků, jistě se vám bude hodit asp:Localize, které slouží k snadnému definování míst, která mají být nahrazována texty z resource souboru. Nebudu teď řešit jak rozhodnout jaký jazyk zvolit, můžete ho mít natvrdo nastavený ve web.config souboru pro jednotlivé deployované domény, nebo získat nějaký parametr z routy, nebo nechat zjišťovat jazyk podle uživatelova nastavení prohlížeče. Pokud budete mít zájem o problematiku lokalizace, můžu jí věnovat některý další spot. :)

<asp:Localize runat="server" meta:resourcekey="SomeResource1" />

Lokalizaci pak provedeme v patřičném resx souboru následovně:

<data name="SomeResource1.Text" xml:space="preserve">
  <value>Some text</value>
</data>

SiteMapPath pro drobečkovou navigaci

Další serverovou komponentou, kterou můžete ve svých šablonách pohledů využít je asp:SiteMapPath, které slouží ke generování drobečkové navigace podle struktury definované v souboru Web.sitemap.

<asp:SiteMapPath runat="server">
  <PathSeparatorTemplate> &gt; </PathSeparatorTemplate>
</asp:SiteMapPath>

Xml pro transformaci

Jedním z posledních ze standardně dodávaných serverových komponent, které ještě v MVC fungují je asp:Xml, které slouží ke vkládání XML dat a jejich transformaci pomocí XSLT.

<asp:Xml runat="server" DocumentSource="/content/contact.xml" TransformSource="/content/contact.xslt"/>

ViewType pro silný typ modelu v pohledu

RC verze MVC frameworku přinesla vlastní serverovou komponentu, která určuje silný typ pro vlastnost Model vašeho pohledu. Je to alternativa k dědění z generické ViewPage.

<mvc:ViewType runat="server" TypeName="ViewPage&lt;MyProject.Model.Customer&gt;" />

A dál?

Dál můžete používat komponenty třetích stran, nebo vlastní, které nevyžadují ViewState. Pokud máte jako předka vašich stránek System.Web.Mvc.ViewPage nemáte v šablonách dostupný data binging. I na to je třeba dávat pozor. Do budoucna by mělo dojít k tomu, že helpery, které jsou součástí MVC frameworku, se dočkají i zapouzdření do komponent. Ale k tomu dojde až po vydání verze 1.0. Již dnes však můžete najít jejich předběžnou implementaci v tzv. ASP.NET MVC Futures, které si můžete stáhnout na CodePlexu. Najdete mezi nimi tyto komponenty:

  • ActionLink,
  • DropDownList,
  • TextBox,
  • Password,
  • Label,
  • Hidden a
  • Repeater

Jejich předkem je MvcControl, který zpřístupňuje ViewContext a ViewData. Repeater si třeba zajišťuje DataBinding sám, takže není třeba ho explicitně volat ze stránky. Nevýhoudou však je, že je třeba Evalovat data, protože Repeater není silně typový. Mám takový pocit, že můj generický repeater by měl v MVC fungovat bez problémů. Ještě jsem to nezkoušel, ale nevidím důvod, proč by neměl. Asi provedu revizi a připravím vylepšenou variantu pro MVC.

A to je pro dnešek vše.

Kanonicky proti duplicitám

07.27 - 13. února 2009 | Webdesign

Jedním z velkých problémů dnešních vyhledávačů je duplicitní obsah. Musejí se poprat s velkým množstvím stránek, které vypadají na první pohled shodně a liší se pouze v URL adrese. Jak mají rozhodnout, kterou z těchto adres vrátit uživateli jako jedinou správnou?

Problém duplicitního obsahu

Duplicitní obsah může vzniknout velice jednoduše, nemusí ani dojít ke zkopírování stránky někým jiným. Prostě stačí mít blbě nastavený server a vracet stejný obsah pro URL s i bez www. na začátku. Další možností je, že se vaše adresy dynamických stránek v čase vyvíjí. Začínal jsem s nepěknými adresami ve tvaru clanek.aspx?id=4, pak jsem časem přešel na SEO URL ve tvaru clanek.aspx/4-nejaky-nadpis, později jsem přidal URL rewriter a mé URL vypadaly takto clanek/4-nejaky-nadpis.aspx. Všechny tyto adresy vedou na stejný obsah, ale protože mají jinou URL, jsou to pro vyhledávacího robota různé stránky.

Jako správný poskytovatel obsahu bych měl zajistit, že všechny verze URL jsou stále funkční, ale měly by směřovat na jedinou platnou. Ale jak?

Řešení

Cest k cíli vede samozřejmě spousta. Pokud máte tu možnost, využijte nějaký URL rewriter. Zvolte si kanonickou formu vašich adres a tu všude používejte. Pokud nechcete používat v adresách prefix www., stačí málo.

Na IIS7 s URL Rewriterem přidejte do vašeho web.config souboru do sekce system.webServer/rewrite/rules následující kód:

<rule name="Remove WWW prefix" >
  <match url="(.*)" ignoreCase="true" />
  <conditions>
    <add input="{HTTP_HOST}" pattern="^www\.domain\.com" />
  </conditions>
  <action type="Redirect" url="http://domain.com/{R:1}" redirectType="Permanent" />
</rule>

Na Apachi stačí do souboru .htaccess přidat následující řádky:

# Remove WWW prefix
RewriteCond %HTTP_HOST ^www\.domain\.com [I]
RewriteRule ^/(.*) http://domain.com/$1 [RP]

Co ale dělat, pokud nemáte na serveru možnost URL rewriting provádět?

Naštěstí existuje alternativa. Vývojáři Google, Yahoo a Live Search se domluvili na zavedení link tagu, který určuje kanonickou URL přímo v dokumentu. Do sekce html/head vašich stránek přidejte následující tag:

<link rel="canonical" href="http://domain.com/kanonicka/adresa-stranky" />

Tím dosáhnete toho, že pokud crawler navštíví vaši stránku přes různé adresy, vždy ji bude považovat za jednu a tu samou s adresou, která je hodnotou atributu href.

Novinky z karavany

06.00 - 12. února 2009 | Webdesign

Ano, je to tak, jak možná někteří tušíte, chystám se psát o tom, co je nového v Twaregu. A únor není na novinky chudý.

Ale začnu hezky od začátku roku, kdy jsme mezi nás přivítali nového člena Miloše Savaru, který se přidal do týmu reklamního systému codename „Hyas“ a pracuje na veřejném API. Jádro zatím podstupuje zátěžové testy. :) Náš komunitní projekt už podporuje OpenID včetně načítání údajů profilu, přibyla schopnost lokalizace pomocí IP adresy a fulltextové hledání.

Dev platforma se nám rozrostla o nový silný stroj a tak došlo k přeinstalování serverů, změně rolí a jmen. Nově používáme jména hadů. Taky se nám dostalo jednoho bladea. A to už se pomalu dostáváme ke spuštění našich webových stránek Twareg.com. Zatím tam není moc obsahu, ale věřím, že bude postupně přibývat. :) Zatím tam najdete náš kontakt, náš tým a nabídku práce. Sice od příštího týdne získáme další posilu týmu, ale pořád sháníme další schopné lidi.

Krom stránek jsem spustili i vlastní twitter: štěbetání tuarégů.

Na stránkách si také můžete všimnout, že jsme se stali členy BizSparku. Ačkoli jsme se na české pobočce Microsoftu dozvěděli, že tento program pro podporu start-upů není pro Českou Republiku určen, tak v programu jsme a můžeme čerpat jeho výhody. Pokud netušíte, co to je BizSpark, tak vězte, že je to program pro začínající firmy, které se rozhodnou vyvíjet na MS platformě. Program je to tříletý. Během této doby máte předplatné MSDN včetně licencí do produkčního prostředí. A to vše za $100. Po uplynutí třech let, tedy zaplatíte $100 a všechny licence, které jste do té doby získali, vám zůstanou.

Tak nám držte palce, pokud chcete, přijďte se na nás podívat, případně zvažte, jestli u nás nechcete pracovat. :)