JellyPot implicitně nepředpokládá žádnou konkrétní strukturu webu. Nepředpokládá tedy ani žádnou podobu menu a další navigace. Struktura dat v administraci může být – a obvykle je – odlišná od struktury webu samotného. Pro vytvoření menu je tedy nutné specifikovat:
- strukturu stránek v souboru v pagemap.config,
- chování položek menu a jejich označování CSS třídami podle aktuální URL.
Popisu struktury stránek se věnuje pagemap.config, tento článek se zabývá popisem chování odkazů menu. K tomu slouží atribut mark u controlů pro tvorbu odkazů <je:a> a <je:aVar> (příp. <je:elem>). S jeho pomocí lze označit jimi generované HTML tagy zvolenou třídou.
<je:a runat="server"
href="/en/some-page.aspx"
mark="active by page">Some page</je:a>
Poznámka 1: Vše zde uvedené předpokládá, že menu je umístěno ve společném masteru nebo uživatelském controlu nebo obsahuje odkazy generované controlem <je:aVar>. Pokud by totiž bylo zopakováno v každém .aspx a obsahovalo jen statické odkazy, nebylo by nutné se zabývat jejich označováním. Bylo by možné je snadno označit ručně.
Poznámka 2: Pokud nemáte v Pagemap.config definovanou strukturu webu nebo ji máte definovanou chybně (tj. v rozporu se strukturou menu), bude se přiřazování tříd chovat divně a nepředvídatelně.
Syntaxe
Hodnotou atributu mark je řetězec, který definuje, v jakém případě a jakou třídou má být HTML tag vygenerovaný controlem označen. Syntaxe je následující:
mark="class-name by case, class-name by another-case"
kde class-name je jméno třídy, která bude elementu přiřazena, pokud nastane případ case (resp. another-case). Čárkou se oddělují jednotlivé bloky, které jsou vyhodnocovány nezávisle na ostatních. class-name může být i více tříd, pak se zapíše prostě jako
mark="class-name-1 class-name-2 by case"
Případy case JellyPot rozeznává následující:
- page – vygenerovaný HTML element bude označen danou třídou, pokud se aktuální URL shoduje s URL uvedenou v jeho atributu
hrefbez ohledu na případnou proměnnou v URL obsaženou - var – vygenerovaný HTML element bude označen danou třídou, pokud se proměnná obsažená v aktuální URL shoduje s proměnnou obsaženou v URL uvedené v jeho atributu
href - pageGroup – vygenerovaný HTML element bude označen danou třídou, pokud se aktuální URL shoduje s URL v jeho atributu href nebo pokud se aktuální URL shoduje s URL libovolné podstránky podle definice v Pagemap.config
- virtualGroup – vygenerovaný HTML element bude označen danou třídou, pokud se aktuální URL shoduje s URL libovolné podstránky daného elementu virtual podle definice v Pagemap.config
Controly podporující atribut mark
Atribut mark lze použít s controly <je:a>, <je:aVar> a <je:elem>. Každý má trochu jiný užitek a hodí se k něčemu jinému. Pokud je potřeba označit třídou přímo odkaz (tj. HTML element <a>), pak se mark použije s controly <je:a> nebo <je:aVar>:
<je:a runat="server"
href="/en/some-page.aspx"
mark="active by page">Some page</je:a>
Nebo pro <je:aVar> uvnitř <je:repeater>:
...
<je:aVar runat="server"
href="/en/some-item-page.aspx"
mark="active by page">...</je:a>
...
Pokud je potřeba třídou označit jiný element než přímo odkaz – například <li>, který odkaz obaluje – pak se použije <je:elem>:
<je:elem runat="server"
tag="li"
mark="active by page">
<je:a runat="server"
href="/en/some-page.aspx">Some page</je:a>
</je:elem>
V takovém případě se vyhledá první control <je:a> (resp. <je:avar>) v <je:elem> obsažený a výraz mark se vyhodnotí jako by byl uveden přímo na <je:a> (resp. <je:avar>). Controly <je:a> nebo <je:avar> přitom musí být bezprostředními potomky <je:elem>, dále do hloubky se kód neprohledává. (To je sice obecně omezující, ale vzhledem k použití to stačí a renderování stránky je výrazně rychlejší.)
Případy pro přiřazení tříd
by page
Vygenerovaný HTML element bude označen danou třídou, pokud se aktuální URL shoduje s URL uvedenou v jeho atributu href. Má smysl u: <je:a> (příp. <je:elem> který obsahuje <je:a>)
<je:a runat="server"
href="/en/some-page.aspx"
mark="my-class by page">Some page</je:a>
V uvedeném příkladu bude odkaz označený třídou my-class, pokud URL aktuální stránky je /en/some-page.aspx.
page se používá typicky pro statické odkazy. Pokud by v URL aktuální stránky byla obsažena proměnná, by page ji prostě ignoruje. Tedy např. URL:
/en/other-page/my-hovercraft-123xyz.aspx /en/other-page/is-full-of-eels-567abc.aspx /en/other-page.aspx
jsou považovány za shodné. Jinými slovy by page porovnává URL stránky bez proměnné.
Lze použít zkrácenou verzi mark="my-class". Tento zápis je ekvivalentní s mark="my-class by page".
by var
Vygenerovaný HTML element bude označen danou třídou, pokud se proměnná obsažená v aktuální URL shoduje s proměnnou obsaženou v URL uvedené v jeho atributu href. Má smysl u: <je:aVar> (příp. <je:elem> který obsahuje <je:aVar>).
...
<je:aVar runat="server"
href="/en/some-page.aspx"
mark="my-class by var">
...
</je:aVar>
...
Protože var porovnává URL včetně obsažené proměnné, jsou např. URL:
/en/other-page/my-hovercraft-123xyz.aspx /en/other-page/is-full-of-eels-567abc.aspx /en/other-page.aspx
považovány za rozdílné.
Odkaz bude danou třídou označen i v případě, pokud jeho URL obsahuje proměnnou, která je podle deklarace v Site.config libovolně hierarchicky nadřazená proměnné obsažené v aktuální URL.
by pageGroup
Vygenerovaný HTML element bude označen danou třídou, pokud se aktuální URL shoduje s URL v jeho atributu href nebo pokud se aktuální URL shoduje s URL libovolné podstránky podle definice v Pagemap.config. Má smysl především u: <je:a> a <je:elem>.
<je:a runat="server"
href="/en/my-group.aspx"
mark="my-class by pageGroup">My Group</je:a>
V uvedeném příkladu bude odkaz označen třídou my-class, pokud je aktuální URL /en/my-group.aspx nebo pokud je aktuální URL podstránkou /en/my-group.aspx podle definice v Pagemap.config.
by virtualGroup
Vygenerovaný HTML element bude označen danou třídou, pokud se aktuální URL shoduje s URL libovolné podstránky daného elementu virtual podle definice v Pagemap.config. Má smysl především u: <je:elem>.
<je:elem runat="server"
mark="my-class by virtualGroup myGroup">My Group
<je:a runat="server"
href="/en/some-page-in-my-group.aspx">Some Page</je:a>
<je:a runat="server"
href="/en/another-page-in-my-group.aspx">Another Page</je:a>
</je:elem>
V uvedeném příkladu bude obalující element označen třídou my-class, pokud aktuální URL je /en/some-page-in-my-group.aspx nebo /en/another-page-in-my-group.aspx a tyto jsou podle definice v Pagemap.config podstránkami elementu virtual pojmenovaného myGroup.
Příklad
Máme web, který obsahuje:
- homepage
- stránku s produkty a jejich detaily
- stránku o nás, která má dvě další podstránky
Menu by mohlo vypadat třeba takto:
Při kliknutí na libovolnou položku je uživatel okamžitě odkázán na odpovídající stránku. Menu má pouze jednu úroveň. Zároveň ale chceme, aby se zvýraznila příslušná položka menu v případě, kdy je uživatel na podstránkách (například detailu produktu nebo historii společnosti).
Struktura v Pagemap.config je definovaná takto:
<JellyPotDef xmlns="urn:Bet:ns:JellyPot:PagemapConfig">
<SiteMap>
<Page href="/en/default.aspx" />
<Page href="/en/products.aspx">
<Page href="/en/products/product.aspx" />
</Page>
<Page href="/en/about.aspx">
<Page href="/en/about/our-values.aspx" />
<Page href="/en/about/our-history.aspx" />
</Page>
</SiteMap>
</JellyPotDef>
Menu v master stránce by vypadalo takto:
<je:a runat="server"
href="/en/default.aspx"
mark="active by page">Home</je:a>
<je:a runat="server"
href="/en/products.aspx"
mark="active by pageGroup">Products</je:a>
<je:a runat="server"
href="/en/about.aspx"
mark="active by pageGroup">About us</a>
Kdybychom chtěli, aby menu by bylo roletkové, tj. položky Products a About by nevedly na samostatné stránky, na kliknutí by pouze rozbalovaly podmenu. Stránky Products a About by tedy neexistovaly, byly by jen logické ( = virtuální), strukturu webu bychom si mohli představit takto:
A menu bychom chtěli třeba takovéto:
Při kliknutí na Products nebo About se vybalí menu druhé úrovně, stránky Products nebo About fakticky vůbec neexistují – jsou jenom logickým seskupením nějakých jiných stránek.
V Pagemap.config by definice struktury vypadalo takto:
<JellyPotDef xmlns="urn:Bet:ns:JellyPot:PagemapConfig">
<SiteMap>
<Page href="/en/default.aspx" />
<Virtual name="products">
<Page href="/en/products/product.aspx" />
</Virtual>
<Virtual name="about">
<Page href="/en/about/our-values.aspx" />
<Page href="/en/about/our-history.aspx" />
</Virtual>
</SiteMap>
</JellyPotDef>
Menu v master stránce by bylo následující:
<je:a runat="server"
href="/en/default.aspx"
mark="active by page">Home</je:a>
<je:elem runat="server" tag="div" mark="active by virtualGroup products">
Products
<div>
<je:repeater runat="server">
<item>
<je:aVar runat="server"
href="/en/"
mark="active by var">
<je:item runat="server" field=".title" />
</je:aVar>
</item>
</je:repeater>
</div>
</je:elem>
<je:elem runat="server" tag="div" mark="active by virtualGroup about">
About us
<div>
<je:a runat="server"
href="/en/about/our-values.aspx"
mark="active by page">
<je:item runat="server" field=".title" />
</je:a>
<je:a runat="server"
href="/en/about/our-history.aspx"
mark="active by page">
<je:item runat="server" field=".title" />
</je:a>
</div>
</je:elem>
Pochopitelně je možné na jednom webu kombinovat pageGroup a virtualGroup. Jen v našem jednoduchém případě by to vedlo k podivně se chovajícímu menu (některé položky by rozbalovaly podmenu, jiné by rovnou vedly na stránky) a to by asi nikdo nechtěl (odkaz na homepage je běžná výjimka ;). Typická situace, kdy by se kombinovaly, je, pokud je menu víceúrovňové. Pak první uroveň je třeba pageGroup, druhá virtualGroup.