So programmierst du einen RSS-Reader in 30 Minuten (Teil 1/2)
Im Rahmen zweier Tutorials erkläre ich, wie man von Grund auf einen kleinen RSS-Reader programmiert – und zwar mit HTML5, CSS3 und WinJS, dem Microsoft-JavaScript-Framework für Windows 8. Wir werden anschließend eine Windows-RT-App für den Windows-Store erstellen, die den Gestaltungsprinzipien von Windows-8-UI folgt und Expression Blend 5 verwendet. An und für sich sollte das Durcharbeiten dieser beiden Artikel in 30 Minuten erledigt sein.
Der erste Artikel erklärt das Erstellen des Startbildschirms, der ein WinJS-ListView-Steuerelement verwenden wird. Dieses Element wird alle kürzlich veröffentlichten Blog-Posts durch hübsche Thumbnails anzeigen. Der zweite Artikel geht auf die Detailansicht ein, die ihr nach dem Klick auf einen der Listeneinträge seht. Am Ende des Tutorials findet ihr die fertige Lösung zum Download. Betrachtet den Quellcode als hilfreiche, kostenlose Referenz, falls einige Teile des Artikels weiterer Klärung bedürfen.
Voraussetzungen: Um diesen Artikeln folgen zu können, müsst ihr zuerst Folgendes tun:
- Ladet euch Windows 8 RTM auf Ihren Computer und installiert es: http://msdn.microsoft.com/en-US/windows/apps/br229516.aspx (hier gibt es eine kostenlose 90-Tage Trial-Version).
- Ladet euch Visual Studio 2012 Express RTM for Windows 8 und installiert es: http://msdn.microsoft.com/en-US/windows/apps/br229516.aspx (Diese Version ist kostenlos, aber ihr könnt natürlich auch eine kommerzielle Version verwenden).
Anmerkung: Keine Panik, wenn ihr einen Mac habt. Dank BootCamp funktioniert trotzdem alles perfekt oder ihr könnt es auch in einer virtuellen Maschine, zum Beispiel in Parallels, laufen lassen.
Anmerkung 2: Dieser Artikel wurde am 21. August 2012 überarbeitet, um die Änderungen in der UI und dem Code zwischen Windows 8 Release Preview und RTM zu berücksichtigen. Wollen Sie eine eigene Anwendung von der Release Preview migrieren, sollten Sie dieses Dokument lesen: „braking changes document”. In unserem Fall waren lediglich Teile betroffen, die mit der neuen UI und Benennungen in Visual Studio zu tun hatten.
Anmerkung 3: Ich habe noch einen extra Beitrag veröffentlicht, der WordPress und Community gewidmet ist: „Windows 8 HTML5 Metro Style App: RSS reader in 30min – building your WordPress version”
Hier ist ein kurzer Überblick des Inhalts des ersten Teils:
- Schritt 1: Eine leere Anwendung erstellen
- Schritt 2: Das HTML & CSS Grundgerüst unserer Hauptseite erstellen
- Schritt 3: Erster Kontakt mit Blend
- Schritt 4: Daten mit XHR laden und diese an das ListView-Steuerelement binden
- Schritt 5: Ein Template benutzen und das Design mit Blend verändern
- Schritt 6: Quellcode zum Herunterladen
Beachtet bitte: Diese Tutorials basieren auf der BUILD-Session „Tools for building Metro style apps” mit Chris Sell und Kieran Mockford. Ich habe den Inhalt lediglich für Windows 8 RTM aktualisiert.
Schritt 1: Eine leere Anwendung erstellen
Ruft Visual Studio 2012 auf, geht auf File -> New Project und erstellt ein neues JavaScript -> Windows Store -> Blank-App-Projekt:
Benennt euer Projekt „SimpleChannel9Reader”, da wir den RSS-Feed aus dem Coding4Fun-Bereich auf Channel9 herunterladen werden. Hier ist die URL: http://channel9.msdn.com/coding4fun/articles/RSS
Schritt 2: Das HTML & CSS Grundgerüst unserer Hauptseite erstellen
Öffnet die Datei „default.html”. Sie beschreibt die erste Seite , die beim Start der Anwendung angezeigt wird. Anstelle des folgenden HTML-Teils:
<p>Content goes here</p>
Fügt ihr diesen Teil ein:
<div id="main"> <header id="banner"> <button id="backbutton"></button> <h1 id="maintitle">Welcome to Channel 9!</h1> </header> <section id="content"></section> </div>
Wir haben jetzt einen globalen <div>-Container mit der ID „main” und zwei inneren Containern genannt „banner” und „content”. Der <header> wird natürlich oben auf der Seite dargestellt und die <section> mit dem Inhalt direkt darunter. Lasst uns hierzu ein wenig CSS hinzufügen, indem wir die Datei „default.css” öffnen, die im „css”-Ordner liegt. Ihr werdet sehen, dass es schon einige vordefinierte CSS-Regeln gibt, um die verschiedenen verfügbaren Windows-8-Ansichten über Media Queries zu formatieren. In diesen beiden Artikeln konzentriere ich mich auf die „fullscreen-landscape“-Ansicht. Also springt direkt zu diesem Bereich und fügt das folgende CSS ein:
#main { width: 100%; height: 100%; } #banner { width: 100%; height: 100%; } #backbutton { } #maintitle { } #content { width: 100%; height: 100%; }
Dies sorgt dafür, dass der verfügbare Platz für die drei Hauptcontainer verwendet wird.
Lasst eure Anwendung laufen, indem ihr die F5-Taste drückt oder auf den folgenden Button klickt:
Ihr solltet nun dieses Bild sehen:
Und ihr solltet auch ein offensichtliches Gestaltungsproblem erkennen: Der Zurück-Button und der Titel sind nicht nebeneinander angeordnet. Lösen lässt sich das Problem mit Blend 5!
Schritt 3: Erster Kontakt mit Blend
Startet Blend und geht zum Ordner, wo sich euer SimpleChannel9Reader-Projekt befindet. Blend wird dann Folgendes anzeigen:
Das Ziel ist, zwei Raster (Grid) zu erstellen. Das erste ist für den main-Container. Es umfasst eine Spalte, die die volle Breite einnimmt sowie zwei Zeilen. Das zweite Raster ist definiert durch eine Zeile und zwei Spalten für den Zurück-Button und den Titel.
Beginnen wir mit der Auswahl des main-Elements, indem wir das Live-DOM-Fenster verwenden:
Geht zu „CSS Properties“, wählt die #main-Regel im Layout-Fenster aus und ändert den Wert für display auf „-ms-grid”:
Wir werden die CSS-Grid-Layout-Spezifikation verwenden, die zurzeit nur vom IE10 unterstützt wird, aber bald auch von anderen Browsern beherrscht werden sollte. Wenn ihr mehr über die Art von Layout erfahren wollt, die im Metro-Mode unterstützt wird, könnt ihr diesen Artikel lesen: Choosing a CSS3 layout for your app.
Wenn ihr die Möglichkeiten in der CSS3-Grid-Spezifikation entdecken wollt, dann spielt ein wenig mit dieser IE Test Drive Demo: Hands On: CSS3 Grid Layout
Nach dem Zuweisen des notwendigen grid-Werts zur Eigenschaft display müssen wir nun unser Raster definieren. Springt hierfür zu dem Bereich „Grid” und setzt die folgenden Eigenschaften:
Wir werden eine einzige Spalte über die gesamte Breite des Displays (was auch immer die Auflösung sein wird) und zwei Zeilen haben. Die erste Zeile wird eine feste Höhe von 132px haben und die andere wird die restliche verfügbare Höhe einnehmen. Ihr könnt dies in der Blend-Designeroberfläche sehen:
Nun werden wir das content-Element in die zweite Zeile packen. Wählt dazu im „Live DOM” aus, klickt auf die #content-Regel und geht dann zu dessen Grid-Eigenschaften. Ändert den Wert von „-ms-grid-row” auf 2. Ihr könnt auch das banner-Element in die Zeile 1 packen; dies ist ohnehin die Voreinstellung, auch wenn ihr es nicht ausdrücklich setzt.
Nun werden wir unsere erste Zeile in zwei Spalten teilen, um jedes der beiden Elemente an seinen richtigen Platz zu setzen. Wählt das banner-Element aus, ändert seine display-Eigenschaft auf „-ms-grid” und definiert eine 1fr breite Zeile und zwei Spalten, die erste 120px breit und die zweite 1fr:
Setzt das maintitle-Element in die Spalte 2 und zentriert es vertikal, indem ihr die Eigenschaft „-ms-grid-row-align” auf center stellen:
Wählt das backbutton-Element aus und geht zum Layout-Teil. Setzt den oberen Abstand (top margin) auf 54px und den linken Abstand (left margin) auf 40 px. Wenn ihr bisher nichts vergessen habt, solltet ihr jetzt Folgendes auf der Designoberfläche sehen:
Speichert alle Änderungen mit File -> Save All und kehrt zu Visual Studio zurück. Öffnet die Datei „default.css” und ihr werdet sehen, dass Blend bei den richtigen CSS-Regeln einige „saubere” Ergänzungen vorgenommen hat:
@media screen and (-ms-view-state: fullscreen-landscape) { #main { width: 100%; height: 100%; display: -ms-grid; -ms-grid-columns: 1fr; -ms-grid-rows: 132px 1fr; } #banner { width: 100%; height: 100%; display: -ms-grid; -ms-grid-columns: 120px 1fr; -ms-grid-rows: 1fr; } #backbutton { margin-top: 54px; margin-left: 40px; } #maintitle { -ms-grid-column: 2; -ms-grid-row-align: center; } #content { width: 100%; height: 100%; -ms-grid-row: 2; } }
Checkt kurz, ob die Anwendung wie erwartet funktioniert, indem ihr einfach F5 drückt.
Schritt 4: Daten mit XHR laden und diese an das ListView-Steuerelement binden
Nun geht’s an den Programmcode: Als erstes müssen wir das Steuerelement einfügen, das die Thumbnails unserer Artikel auf dem Startbildschirm anzeigt. Wir werden hierzu WinJS verwenden.
Die WinJS Library oder „Microsoft Windows Library for JavaScript SDK” hilft JavaScript-Entwicklern beim Umgang mit der neuen UI von Windows 8. Es stellt eine Reihe von Steuerelementen zur Verfügung, eine Templating-Engine, eine Binding-Engine, Promises um asynchrone JavaScript-Aufrufe zu verarbeiten, Hilfsfunktionen die sich um Namensräume kümmern und so weiter.
Mehr Details über die Steuerelemente finden sich in diesem Artikel: „Quickstart: adding WinJS controls and styles”.
In Windows-Store-Projekten findet ihr die WinJS Library im „Solution Explorer” unter References.
Darunter werdet ihr die Standard-Stylesheets mit den zwei dunklen und einem hellen Theme sehen sowie den Javascript-Code. Das Studieren des Codes lohnt sich auf jeden Fall, man kann dadurch immer etwas lernen.
In unserem Fall werden wir das ListView-Steuerelement verwenden, das zur Anzeige der Elementliste ein Raster-Layout erstellt.
Öffnet die Datei „default.html” und fügt diese HTML-Zeile in den <section>-Tag ein:
<div id="articlelist" data-win-control="WinJS.UI.ListView"></div>
Momentan ist es nur ein einfacher, klassischer <div>. In ihm ist jedoch bereits das Attribut data-win-control gesetzt. Dies deutet an, dass wir die WinJS-Library benutzen möchten, um diesen einfachen <div> in ein JavaScript-ListView-Steuerelement umzuwandeln.
Dies wird ausgeführt mithilfe einer Zeile JavaScript-Code, die ihr in der „default.js” finden könnt:
WinJS.UI.processAll();
Diese asynchrone Funktion verarbeitet die gesamte DOM-Struktur, um Elemente zu finden, die mit dem Attribut „data-win-control” markiert sind und wandelt diese in echte WinJS-Steuerelemente um. Für den Entwickler bedeutet das den einfachen Zugang zur neuen Windows-8-UI. Wenn ihr diese Zeile aus Versehen löscht, wandeln sich alle eure <div>-Elemente wieder zurück in einen einfachen <div>-Tag.
Nun müssen wir diesen ListView mit Daten des RSS-Feeds füttern. Fügt dazu in der bind-Funktion zum Event „onactivated” direkt oberhalb der processAll()-Zeile folgenden Code ein:
articlesList = new WinJS.Binding.List(); var publicMembers = { ItemList: articlesList }; WinJS.Namespace.define("C9Data", publicMembers);
Nun müsst ihr die Variable „articlesList“ am Anfang der Funktion deklarieren, zum Beispiel gleich nach der Variable „app“.
Wir deklarieren hier eine Variable vom Typ Binding.List(). Diesen Typen benutzen wir, um eure Daten an die WinJS-Steuerelemente zu binden. Er enthält beispielsweise einige Methoden, die euch helfen werden, einige Daten im Hintergrund hinzuzufügen und dank des Binding-Mechanismus spiegeln sich diese Änderungen automatisch in der Ansicht wider.
Darüberhinaus ist euch vielleicht aufgefallen, dass wir sauberen JavaScript-Code verwenden, indem wir moderne Muster anwenden, wie das „Modulmuster“. Hierfür haben wir eine anonyme selbst-ausführende JS Funktion in „default.js”. Dann müssen wir einen Weg finden, um öffentliche (public) Daten für externe Funktionen verfügbar zu machen. Deswegen implementieren wir Namensräume für die entsprechenden WinJS-Hilfsfunktionen. Dadurch können wir ganz einfach definieren, was wir verfügbar machen wollen. In unserem Fall werden wir ein öffentliches (public) Objekt namens „C9Data“ verfügbar machen, das eine ItemList-Eigenschaft besitzt, die wiederum unsere später anzuzeigenden Elemente enthält.
Jetzt brauchen wir eine Funktion, die sich die Daten vom RSS-Feed holt, sie verarbeitet und on-the-fly ein paar JS-Objekte erstellt, um sie in die berühmte Binding-Liste zu schieben:
function downloadC9BlogFeed() { WinJS.xhr({ url: "http://channel9.msdn.com/coding4fun/articles/RSS" }).then(function (rss) { }); }
Diese Funktion beginnt damit, einen asynchronen XmlHttpRequest zu der angegebenen URL zu senden. Der Code, der in der Promise (dem .then()-Teil) definiert ist, wird dann ausgeführt – aber nur, wenn der Request abgeschlossen und die Daten erhalten wurden. An dieser Stelle müssen wir dann die Daten filtern, indem wir den folgenden Code in die anonyme Funktion einfügen:
var items = rss.responseXML.querySelectorAll("item"); for (var n = 0; n < items.length; n++) { var article = {}; article.title = items[n].querySelector("title").textContent; var thumbs = items[n].querySelectorAll("thumbnail"); if (thumbs.length > 1) { article.thumbnail = thumbs[1].attributes.getNamedItem("url").textContent; article.content = items[n].textContent; articlesList.push(article); } }
Ich hoffe, dieser Code ist selbsterklärend. Er sucht alle item-Knoten, greift auf ihre interessanten Eigenschaften zu, um diese auf ein article-Objekt abzubilden, das on-the-fly mit den Eigenschaften title, thumbs und content erstellt wird. Bitte merkt euch die Namen dieser Eigenschaften; wir werden sie später wieder verwenden. Zum Schluss fügt die Funktion das neue Objekt der Binding-Sammlung hinzu.
Jetzt müssen wir diese Funktion während der Startphase unserer Anwendung aufrufen. Dieser Code sollte nur nach dem Verarbeiten der DOM-Struktur ausgeführt werden, um die WinJS-Steuerelemente zu erstellen:
WinJS.UI.processAll().then(downloadC9BlogFeed);
Wir müssen dem Steuerelement seine Datenquelle übergeben. Springen wir also zurück zum HTML-Code und ändern die Optionen des <div>, der dem ListView-Element entspricht:
<div id="articlelist" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: C9Data.ItemList.dataSource }"></div>
Zum Schluss benötigen wir noch ein wenig grundlegendes CSS, damit das Steuerelement weiß, wie es jeden seiner Einträge formatieren soll. Geht also zur Datei „default.css” und fügt diese beiden Regeln hinzu:
#articlelist { width: 100%; height: 100%; } #articlelist .win-item { width: 150px; height: 150px; }
Das CSS beschreibt, dass unser ListView-Steuerelement den ganzen verfügbaren Platz in seinem Container in Anspruch nehmen soll und dass jeder seiner Einträge (durch die „.win-item”-Klasse) 150px mal 150px groß sein soll.
Führt den Code durch Drücken von F5 aus. Ihr werdet etwas sehen, dass so hässlich ist, wie das hier:
Aber keine Sorge, der hässliche Output ist das zu erwartende Verhalten. Wir haben noch ein bisschen Designarbeit vor uns. Aber ihr könnt bereits sehen, dass das Binding korrekt ist und dass die Bedienung des Steuerelements sowohl per Touch als auch mit Mausklicks ordnungsgemäß funktioniert. Darüberhinaus passt sich die Größenverteilung des Steuerelements automatisch an sämtliche Auflösungen an. In diesem Fall werdet ihr nicht das exakt selbe Layout (Anzahl der angezeigten Spalten und Zeilen) zu sehen bekommen, wie oben im Bild dargestellt.
Schritt 5: Ein Template benutzen und das Design mit Blend verändern
Jetzt müsst ihr die Darstellung der Elemente ändern. Genau das ist der Zweck einer Template-Engine. Ein Template ist nichts Anderes als ein wenig HTML, das mit einigen WinJS-Attributen versehen ist.
Geht zur „default.html”-Seite und fügt das folgende HTML direkt über dem main-Teil ein:
<div id="C9ItemTemplate" data-win-control="WinJS.Binding.Template" style="display: none;"> <div> <div> <img data-win-bind="src: thumbnail" /> </div> <div data-win-bind="innerText: title"></div> </div> </div>
Es ist ein HTML-Template, markiert mit dem Wert „WinJS.Binding.Template”. Dies wird WinJS beim Umgang mit diesem speziellen HTML-Teil nach dem Ausführen von processALL() helfen. Ihr werdet auch den Einsatz von „data-win-bind” bemerkt haben. Hiermit werden Ausdrücke definiert, die der Binding-Engine sagen, welche JavaScript-Eigenschaften von der Datenquelle auf welchen HTML-Knoten abgebildet werden sollen. Der Rest ist ganz normaler HTML-Code.
Nun müssen wir das WinJS-Steuerelement so konfigurieren, dass es nicht mehr das Standard-Template verwendet, sondern das neue oben gezeigte Template. Dazu ändert man einfach die Optionen:
<div id="articlelist" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: C9Data.ItemList.dataSource, itemTemplate: C9ItemTemplate }"> </div>
Wenn ihr die Anwendung jetzt laufen lasst, solltet ihr folgendes sehen:
Schon besser, aber wir sind noch nicht fertig. Um das Design noch weiter zu verfeinern holen wir wieder Blend zu Hilfe.
Gehen wir also zurück zu Blend. Blend wird euch bitten, alle Änderungen, die ihr in Visual Studio vorgenommen habt, neu zu laden. Sobald Sie das getan haben, seht ihr folgendes:
Ihr seid nicht überrascht? Das solltet ihr aber sein. Denn ihr seht tatsächlich die selbe visuelle Darstellung, die nach dem Drücken von F5 in Visual Studio zu sehen ist. Das bedeutet, dass Blend den JavaScript-Teil eurer Anwendung innerhalb des Designers dynamisch ausführt. Das ist eine erstaunliche Funktion.
Dank dieser Fähigkeit könnt ihr direkt mit echten Daten arbeiten. Ihr müsst also anstelle der echten Daten nicht erst mit „Pseudoinhalten” gestalten. Das ist das Coole an JavaScript. Blend ist in der Lage, den JS-Code auszuführen, der die XHR-Anfrage absetzt und die WinJS-Objekte zu erstellen.
Unter „default.css” können wir jetzt noch zwei neue CSS-Regeln hinzufügen. Klickt auf den +-Button des Haupt-Media-Query:
Und fügt diese neuen Selektoren hinzu:
.listItemTemplate
.listItemTemplate img
Wählt die Regel #articlelist .win-item, die jedes Element im ListView hervorhebt, welches die ID „articlelist“ hat.
Ändert die Größe dieser Elemente von 150px mal 150px auf 250px mal 250px. Ihr braucht dazu nur in der rechten Leiste in den Sizing-Bereich gehen.
Das Layout sollte dynamisch aktualisiert werden. Wenn nicht, könnt ihr ein Aktualisieren des Designs forcieren, indem ihr auf den dafür vorgesehenen Button klickt:
Und hier ist das Ergebnis, das ihr sehen solltet:
Jetzt werden wir die Größe der Bilder im Template ändern. Verwendet hierzu das Auswahl-Werkzeug (Pfeil) und klickt auf eines der Bilder:
Ihr könnt die aktuell angewendeten CSS-Regeln im Bereich „Applied Rules” sehen. Klickt auf „.listItemTemplate img” und verändert mit der Maus die Größe des momentan ausgewählten Bildes. Alle anderen Bilder, die vom selben Selektor angesprochen werden, werden sich dann dynamisch in Echtzeit mitverändern. Die passende Größe in diesem Fall erzielt ihr durch Eingabe von 234px Breite und 165px Höhe im Sizing-Bereich.
Um das Design noch ein wenig zu verbessern, brauchen wir noch mehr Abstand zwischen den einzelnen Elementen und wir wollen unser ListView-Steuerelement am Titel ausrichten.
Klickt auf den Selektor „.listItemTemplate”, dann geht zum Layout-Bereich und klickt auf das Lock-Symbol (Sperrschloss) rechts neben dem Margin-Bereich. Wählt irgendeinen Abstand, dann tippt 8px ein.
Um das Raster des ListView-Steuerelements am Titel auszurichten, müssen wir ihn schließlich noch 120px von links einrücken, minus 8px, wegen des Element-Abstands, den wir gerade gesetzt haben.
Drückt dazu wieder den +-Button, fügt noch einen neuen Selektor hinzu und nennt ihn „.win-surface”. Setzt einen linken Abstand (margin) von 112px.
Kehrt zurück zu Visual Studio, akzeptiert die vorgenommenen Änderungen und drückt F5. Jetzt solltet ihr das folgende Layout sehen:
Schritt 6: Quellcode zum Herunterladen
Wir haben große Fortschritte gemacht. Jetzt müssen wir nur noch die Details eines Artikels anzeigen, um sowohl weitere Fähigkeiten von Blend zu demonstrieren, als auch einige neue coole CSS3-Funktionen. Ihr könnt den kompletten Quellcode zu den in diesem ersten Artikel besprochenen Lösungen hier herunterladen: Simple Channel9 Reader Article1
Lest weiter im nächsten Artikel zum Thema: Windows 8 HTML5 WinRT App: Wie man einen kleinen RSS-Reader in 30 Minuten erstellt. (Teil 2/2)
Weiterführende Links
- Die t3n-App für Windows 8 ist da – t3n News
- Twitter für Windows 8: App endlich erschienen – t3n News
- Windows 8.1 „Blue“ kommt als kostenloses Update – t3n News
Über den Autor
David Rousset arbeitet bei Microsoft Frankreich als „Windows 8 & HTML5 Microsoft Developer Evangelist“. Sein Twitter-Profil findet ihr unter @davrous.
Duplicate Content! ;-)
Komplettes Tutorial durch und 1:1 nachgebaut, funktioniert nicht!