Windows 8 a Metro: layout aplikace pomocí mřížky

Na podzim jsme se věnovali základům tvorby aplikací pro Windows 8 a rozhraní Metro pomocí JavaScriptu. Teď opět navážeme a ukážeme si vylepšení doposud vytvořené aplikace. Změníme její rozvržení na dva sloupce a trochu upravíme funkcionalitu původní jednoduché RSS čtečky.

Novým čtenářům a těm, kteří na první kroky s Windows Metro již zapomněli, připomínám odkazy na dva předchozí články. V prvním nazvaném Stavíme aplikaci pro Windows 8 s využitím HTML 5 a JavaScriptu – anatomie a základy jsme se podívali na to, jak vůbec aplikace pomocí JavaScriptu a HTML5 pro Windows 8 a jeho rozhraní Metro vytvářet. S potřebnou znalostí jsme pak vytvořili jednoduchou RSS čtečku v článku Programujeme pro Windows 8 a Metro: stahování dat pomocí JavaScriptu. Ukázali jsme si, jak stahovat data ve formátu XML a jak je zpracovat do podoby zobrazitelné v aplikaci.

V tomto článku si aplikaci z předchozího dílu vezmeme jako základ a budeme ji dále vylepšovat. Konkrétně zkusíme předělat stávající rozhraní na dva sloupce. V tuto chvíli aplikace jen stáhne RSS výstup z webu, zpracuje XML a zobrazí články s popisky přes celou šířku okna počítače nebo tabletu.

Až s úpravou aplikace skončíme, bude seznam získaných článků v levé části s posuvníkem a vpravo se pak budou zobrazovat obsahy článků v RSS poté, co na ně uživatel klikne v levé části seznamu.

Pro jistotu připomínám stávající podobu aplikace. Její zdrojový kód si můžete stáhnout z předchozího článku.

Simulátor Windows 8 Visual Studio 11 Visual Studio 11

Úprava HTML struktury - doplnění sloupce pro obsah článku

První úpravou, do které se pustíme, bude doplnění HTML kódu tak, abychom získali strukturu s levým sloupcem se seznamem článků a pro pravý sloupec s obsahem. První, co uděláme, bude odstranění DIVu s id=polozky. Seznam článků totiž budeme nyní zobrazovat v jiné podobě, je v jednom DIVu zabírajícím celou plochu.

První DIV, který následně do těla aplikace přidáme, bude mít identifikátor template a uvnitř něj budou další dva DIVy sloužící k zobrazování titulku článku a jeho data vydání. Celý tento DIV s id=template bude sloužit pro zformátování položek pro levý sloupec se seznamem článků.

    <div id="template" data-win-control="WinJS.Binding.Template">
        <div data-win-bind="innerText: title" class="postTitle"></div>
        <div data-win-bind="innerText: date" class="postDate"></div>
    </div>

Všimněte si, že jednotlivé DIVy mají ještě další atributy kromě tříd a id. Šablona jako taková obsahuje atribut data-win-control s příslušnou hodnotou, kterou systému sdělujeme, že jde o nějakou šablonu napojenou později na konkrétní data. Atributy data-win-bind u vnitřních položek zase specifikují jednotlivá datová políčka, kterými budeme šablonu plnit.

Nyní můžeme připravit strukturu pro levý sloupec se seznamem článků. V podstatě půjde o komponentu ListView, tedy seznam položek s posuvníkem po straně.

{syntaxhighlighter brush: html;fontsize: 100; first-line: 1; }

 

{/syntaxhighlighter}

Všimněte si, že označení komponenty, kterou chceme vytvořit, specifikujeme do již známého atributu data-win-control. Jen místo šablony specifikujeme typ komponenty. Jak později uvidíte, systém tímto DIVem vyrenderuje klasické HTML. Zde je jen o to mu sdělit, že v něm bude seznam nějakých položek a že zde chceme mít onen posuvník.

Jelikož však vytváříme komponentu, ne jen šablonu, musíme ještě někde specifikovat její vlastnosti, což uděláme pomocí atributu data-win-options. Zde jako itemRenderer musíme specifikovat id HTML elementu se šablonou sloužící k zformátování jednotlivých položek seznamu. V našem případě je to id template.

Další tři vlastnosti seznamu určují jeho standardní rozvržení, nastavují jej tak, že půjde vybrat vždy jen jedna položka seznamu a specifikují javascriptovou funkci volanou v momentě, kdy se změní výběr položky v seznamu - tedy ve chvíli, kdy uživatel klepne na jiný záznam.

Nyní následuje poslední část, kterou doplníme do HTML struktury, a sice opět šablona, sloužící tentokrát k zformátování detailu článku, respektive jeho obsahu, který získáme v RSS výstupu.

    <div id="contentTemplate" data-win-control="WinJS.Binding.Template">
        <div data-win-bind="innerText: title" class="postTitle"></div>
        <div data-win-bind="innerText: date" class="postDate"></div>
        <div data-win-bind="innerHTML: content" class="postContent"></div>
    </div>
    <div id="content"></div> 

DIVu se šablonou dáme opět jednoznačné id a patřičně naplněným atributem data-win-control specifikujeme, že se jedná o šablonu. Trojice DIVů uvnitř poslouží pro zobrazení titulku článku, data vydání a jeho obsahu. Příslušné třídy zde slouží jen pro pozdější snadné formátování vzhledu pomocí CSS. Stejně jako u předchozí šablony jsou zde důležité atributy data-win-bind, ve kterých aplikaci informujeme o tom, obsahem kterých datových políček jednotlivé DIVy naplníme. Za šablonou pak následuje DIV pro zobrazení obsahu.

Doplnění obsluhy seznamu článků pomocí JavaScriptu

HTML strukturu, do které se nám v naší jednoduché RSS čtečce pro Windows 8 a rozhraní Metro bude načítat seznam článků z RSS výstupu, máme připravenu. Teď však musíme upravit i javascriptový kód v souboru default.js, který má na starosti obsluhu aplikace a její funkčnost.

V původní podobě po spuštění aplikace načetl data z RSS zdroje, následně je pomocí konstrukce .then() předal asynchronně k dalšímu zpracování a články se zobrazily přes celou obrazovku. Protože jsme si nyní v HTML struktuře připravili šablony pro seznam a detail článku, musíme upravit JavaScript tak, aby nám tyto šablony naplňoval.

Do funkce volané při aktivaci aplikace v WinJS.Application.onmainwindowactivated přidáme jediný řádek s příkazem pro zpracování všech prvků uživatelského rozhraní WinJS.UI.processAll();

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; } WinJS.Application.onmainwindowactivated = function (e) { if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) { statusPanel.innerText = "Stahuji data z RSS"; WinJS.xhr({ url: "https://www.maxiorel.cz/rss.xml" }).then(processPosts, downloadError); WinJS.UI.processAll(); } } {/syntaxhighlighter}

Stále asynchronně voláme funkci processPosts(), která nám zpracovává data z XML pro požadovaný RSS zdroj. Upravíme však vnitřní část funkce. Místo dosavadního přidávání DIVů do HTML struktury aplikace poskládáme pole z titulku, data vydání a obsahu článku. Toto pole pak pro každý záznam z RSS ve smyčce předáváme do pole postItems.

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; } var postItems = []; function processPosts(request) { statusPanel.innerText = ""; var items = request.responseXML.selectNodes("//item"); if (items.length == 0) { statusPanel.innerText = "data se nepodařilo stáhnout"; } for (var i = 0, len = items.length; i < len; i++) { var item = items[i]; var post = { title: item.selectNodes("title")[0].text, date: item.selectNodes("pubDate")[0].text, content: item.selectNodes("description")[0].text.replace(/(<([^>]+)>)/ig, ""), }; postItems.push(post); } posts.winControl.dataSource = postItems; } {/syntaxhighlighter}

Poté, co projdeme všechny záznamy v RSS výstupu, přiřadíme již naplněné pole postItems jako datový zdroj do seznamu článků posts. Pokud marně hledáte jeho deklaraci, vzpomeňte si nebo koukněte na HTML strukturu. Do ní jsme přidávali DIV právě s id=posts.

Nyní se nám tedy upravený JavaScript i HTML struktura již propojují do srozumitelného celku. Datovým zdrojem seznamu článků neboli komponentě ListView říkáme, co bude jejím obsahem. Všimněte si, že ve smyčce, kde zpracováváme každý jednotlivý záznam z RSS, pracujeme s klíči title, date a content. Kouknete-li do HTML, zjistíte, že jejich názvy odpovídají tomu, co jsme si definovali jako obsah jednotlivých políček v šablonách template a contentTemplate pomocí zápisu innerText.

Funkci appendDiv() z minula tak můžete zcela smazat, protože již není potřeba. Její úkol, a sice přidávání obsahu do HTML struktury jsme nahradili právě systémem šablon. Naopak musíme přidat funkci selectionChanged(), kterou jsme v HTML struktuře uvedli coby obsluhu změny výběru článků v komponentě ListView. Tvar této funkce bude následující:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; } function selectionChanged(e) { content.innerHTML = ""; var selection = posts.winControl.selection; if (selection.length) { var post = postItems[selection[0].begin]; var contentTemplate = WinJS.UI.getControl(document.getElementById("contentTemplate")); contentTemplate.render(post).then(function (element) { content.appendChild(element); }); } } {/syntaxhighlighter}

V krátkosti koukněme na to, co funkce selectionChanged() provádí. Nejprve vyprázdní text v obsahové části, tedy v DIVu s id=content. Do proměnné selection přiřadí právě vybraný záznam z komponenty ListView, které jsme dali v HTML struktuře id=posts.

Podmínkou if (selection.length) ověříme, zda je ve výběru nějaká položka a do proměnné post přiřadíme první položku výběru (ve skutečnosti jich více vybrat nejde, což jsme ošetřili při definici seznamu v HTML).

Vytvoříme proměnnou contentTemplate a naplníme ji šablonou stejného názvu definovanou v HTML struktuře. Poté na ni můžeme aplikovat funkci render(), kde jí jako argument předáme momentálně označený řádek v seznamu. Ten obsahuje stejné klíče pro titulek, datum i tělo článku (opět koukněte do HTML a připomeňte si to).

Následně zase asynchronní konstrukcí .then() voláme nějaké zpracování, v tomto případě vložení na základě šablony vyrenderovaného obsahu do DIVu s id=content.

Nyní zbývá do JavaScriptu doplnit definici jmenného prostoru, kterým se odkazujeme z HTML struktury:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; } WinJS.Namespace.define('rssReader', { selectionChanged: selectionChanged }); {/syntaxhighlighter}

Definice dvousloupcového rozvržení pomocí CSS3

Máme připravenu funkční stránku aplikace i její HTML strukturu. Do finální podoby nám chybí poslední krok, kterým je úprava kaskádových stylů. Musíme zde doplnit definici pro dvousloupcové rozvržení aplikace.

Začněme tím, že tělu stránky doplníme zobrazení ve formě mřížky (display: -ms-grid;) s automaticky nastaveným počtem řádků (viz -ms-grid-rows) a rozvržením sloupečků na dvě poloviny o stejné šířce (viz -ms-grid-columns). Jednotka fr je poměrná a udává šířky sloupců v mřížce. Pokud byste tedy chtěli, aby obsahová část byla dvakrát tak široká jako ta první se seznamem článků, změnili byste zápis na (-ms-grid-columns: 1fr 2fr;).

{syntaxhighlighter brush: css;fontsize: 100; first-line: 1; } body { background-color: #fff; color: #000; font-family: Verdana; padding: 8pt; display: -ms-grid; -ms-grid-rows: auto 1fr; -ms-grid-columns: 1fr 1fr; } {/syntaxhighlighter}

Dále je potřeba definovat zobrazení jednotlivých sloupců v mřížce. V prvním bude DIV s id=posts, ve druhém pak DIV s id=content. Jejich definice v CSS bude následující:

{syntaxhighlighter brush: css;fontsize: 100; first-line: 1; } #posts { width: 99%; height: 100%; overflow: auto; -ms-grid-row: 2; -ms-grid-column: 1; } #content { width: 95%; height: 100%; overflow-y: auto; margin-right: 64px; -ms-grid-row: 2; -ms-grid-column: 2; } {/syntaxhighlighter}

Důležité jsou zde především zápisy týkající se umístění v mřížce. Zápis -ms-grid-row: 2; říká, že element bude ve druhém řádku mřížky, kterou tvoří nadřazený element, v našem případě rovnou tělo BODY. Zápis -ms-grid-column pak udává sloupeček mřížky pro umístění elementu v příslušném řádku tabulky. Kompletní vzhled CSS tedy bude následující:

{syntaxhighlighter brush: css;fontsize: 100; first-line: 1; } /* default.css */ body { background-color: #fff; color: #000; font-family: Verdana; padding: 8pt; display: -ms-grid; -ms-grid-rows: auto 1fr; -ms-grid-columns: 1fr 1fr; } a:link, a:visited, a:active { color: #700; font-weight: inherit; } h1 { text-transform: none; font-family: inherit; font-size: 22pt; } #posts { width: 99%; height: 100%; overflow: auto; -ms-grid-row: 2; -ms-grid-column: 1; } .postTitle { color: #0066cc; font-size: 1.2em; font-weight: bold; } .postDate { color: #808080; font-size: 11pt; } .postContent { font-size: medium; line-height: 18px; } #content { width: 95%; height: 100%; overflow-y: auto; margin-right: 64px; -ms-grid-row: 2; -ms-grid-column: 2; } @media screen and (-ms-view-state: full-screen) { } @media screen and (-ms-view-state: fill) { } @media screen and (-ms-view-state: snapped) { } @media screen and (-ms-view-state: device-portrait) { } {/syntaxhighlighter}

Spuštění aplikace v rozhraní Metro

Naši vylepšenou RSS čtečku nyní můžete spustit a podívat se, zda vše funguje, jak jsme zamýšleli. Tedy se zobrazením seznamu článků na levé straně, po výběru některého z nich s jeho detailem na straně pravé. Aplikace by měla vypadat následovně. Pro jistotu ještě přikládám screenshoty s obrazovkami Visual Studia 11 a soubory default.html a default.js.

RSS čtečka pro Windows 8 a Metro

RSS čtečka pro Windows 8 a Metro

Visual Studio 11 Visual Studio 11

Pokud se Vám nebude dařit úprava projektu z minula, můžete si vše vyzkoušet na zdrojových kódech pro tento příklad, který přikládám níže. V dalším pokračování seriálu se podíváme na to, jak této aplikaci velmi jednoduše dodat vzhled stejný, jako mají některé výchozí aplikace v rozhraní Metro.

Příloha Velikost
ukazka_pro_windows_8_maxiorel.zip 253.09 KB
Tagy

Buďme ve spojení, přihlaste se k newsletteru

Odesláním formuláře souhlasíte s podmínkami zpracováním osobních údajů. 
Více informací v Ochrana osobních údajů.

Autor článku: Jan Polzer

Tvůrce webů z Brna se specializací na Drupal, WordPress a Symfony. Acquia Certified Developer & Site Builder. Autor několika knih o Drupalu.
Web Development Director v Lesensky.cz. Ve volných chvílích podnikám výlety na souši i po vodě. Více se dozvíte na polzer.cz a mém LinkedIn profilu.

Komentáře k článku

Přidat komentář

Odesláním komentáře souhlasíte s podmínkami Ochrany osobních údajů

reklama
Moje kniha o CMS Drupal

 

Kniha 333 tipů a triků pro Drupal 9


Více na KnihyPolzer.cz

Sledujte Maxiorla na Facebooku

Maxiorel na Facebooku

Poslední komentáře
Hosting pro Drupal a WordPress

Hledáte český webhosting vhodný nejenom pro redakční systém Drupal? Tak vyzkoušejte Webhosting C4 za 1200 Kč na rok s doménou v ceně, 20 GB prostoru a automatické navyšováním o 2 GB každý rok. Podrobnosti zde.

@maxiorel na Twitteru

Maxiorel na Twitteru