This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Die Informationen in diesem Buch wurden mit größter Sorgfalt erarbeitet. Dennoch können Fehler nicht vollständig ausgeschlossen werden. Verlag, Autoren und Übersetzer übernehmen keine juristische Verantwortung oder irgendeine Haftung für eventuell verbliebene Fehler und deren Folgen. Alle Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt und sind möglicherweise eingetragene Warenzeichen. Der Verlag richtet sich im Wesentlichen nach den Schreibweisen der Hersteller. Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen. Kommentare und Fragen können Sie gerne an uns richten: O’Reilly Verlag Balthasarstr. 81 50670 Köln E-Mail: [email protected]
Bibliografische Information der Deutschen Nationalbibliothek Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
Übersetzung und deutsche Bearbeitung: Ingo Dellwig, Werne Lektorat: Christine Haite, Köln Fachliche Unterstützung: Michael Gerth, Köln Korrektorat: Sybille Feldmann, Düsseldorf Satz: III-satz, www.drei-satz.de Umschlaggestaltung: Karen Montgomery, Boston Produktion: Andrea Miß, Köln Belichtung, Druck und buchbinderische Verarbeitung: Druckerei Kösel, Krugzell; www.koeselbuch.de ISBN 978-3-89721-603-7
Dieses Buch ist auf 100% chlorfrei gebleichtem Papier gedruckt.
Für Erica – und das kleine hüpfende Böhnchen in ihrem Bauch.
Wie Millionen von Menschen habe auch ich mich sofort in mein iPhone verliebt. Anfangs waren Webanwendungen (Web-Apps) die einzige Chance, individuelle Programme auf das Gerät zu bekommen, was für mich in Ordnung ging, da ich ja Webentwickler bin. Als Monate später der App Store angekündigt wurde, war ich total aufgeregt. Ich rannte los und kaufte jedes Buch über Objective-C, das mir in die Finger kam. Da einige meiner Web-Apps schon recht bekannt waren, plante ich, diese als native Anwendungen (Apps) neu zu schreiben, sie in den App Store zu stellen und auf einem riesigen, galoppierenden Geldhaufen in den Sonnenuntergang zu reiten. Die Desillusionierung folgte auf dem Fuße. Ich fand es schwierig, Objective-C zu lernen, und ich wurde durch die Tatsache, dass die Sprache außerhalb der Mac-Programmierung wenig nützlich ist, zusätzlich demotiviert. Xcode und der Interface Builder waren zwar sehr professionell, aber sie waren nicht meine normale Entwicklungsumgebung, und ich fand es schwer, mich an sie zu gewöhnen. Ich war von den ganzen Ringen, durch die ich springen musste, nur um meine App und das iPhone für Tests vorzubereiten, extrem genervt. Der Prozess für die Veröffentlichung der Anwendung im App Store war sogar noch komplizierter. Nachdem ich ein oder zwei Wochen mit diesen Variablen gekämpft hatte, fragte ich mich, warum ich mir diesen ganzen Ärger überhaupt antat. Immerhin waren meine Apps bereits weltweit verfügbar – warum sollte ich also unbedingt im App Store sein? Darüber hinaus kann Apple Apps ablehnen – und macht es auch. Das ist sicherlich ihr gutes Recht, und vielleicht haben sie gute Gründe dafür. Allerdings sieht es von außen betrachtet sehr unberechenbar und willkürlich aus. Versuchen Sie einmal, sich hier hineinzuversetzen (das basiert übrigens auf einer wahren Geschichte): Sie haben etwa 100 Stunden damit verbracht, Objective-C zu lernen. In weiteren 100 Stunden haben Sie eine native iPhone App geschrieben. Nehmen wir an, Ihre App ist bereit für die Premiere, und Sie haben erfolgreich die Herausforderungen des Einreichungsprozesses für den App Store gemeistert. Was passiert dann? Sie warten. Und warten. Und warten noch etwas länger. Wir reden über Wochen und manchmal auch Monate. Schließlich bekommen Sie eine Rückantwort. Und … Ihre
Vorwort |
IX
Anwendung wurde abgelehnt. Was nun? Sie haben trotz des ganzen Aufwands nichts in der Hand. Aber warten Sie, es kann noch schlimmer kommen. Angenommen, Sie bekommen Ihre App genehmigt. Hunderte oder vielleicht sogar Tausende von Menschen laden die Anwendung herunter. Sie haben zwar noch kein Geld bekommen, sind aber auf Wolke sieben. Dann trudeln die ersten Fehlermeldungen ein. Sie finden und beheben den Fehler binnen Minuten, reichen die App erneut bei iTunes ein und warten auf Apples Prüfung der Änderung. Und warten. Und warten noch etwas länger. Verärgerte Kunden geben Ihnen haarsträubende Bewertungen im App Store. Die Verkäufe brechen ein. Und Sie warten immer noch. Sie denken darüber nach, den verärgerten Kunden das Geld zurückzuerstatten, aber die Möglichkeit gibt es im App Store nicht. Sie sind also dazu verdammt, herumzusitzen und Ihre Bewertung abstürzen zu sehen, obwohl der Fehler bereits vor Tagen oder Wochen behoben wurde. Sicher. Diese Geschichte beruht auf den Erfahrungen eines einzelnen Entwicklers. Vielleicht ist es ein Extrem, und die aktuellen Zahlen widerlegen meine These. Das Problem bleibt allerdings bestehen: Wir Entwickler haben keinen Zugriff auf Apples Daten oder die Details des Überprüfungsprozesses im App Store. Bis sich das ändert, ist das Erstellen einer nativen App mit Objective-C ein riskanter Plan. Glücklicherweise gibt es eine Alternative. Sie können Webanwendungen bauen, indem Sie frei verfügbare, standardisierte Webtechnologien einsetzen, sie als Web-App veröffentlichen und von echten Anwendern unter Volllast testen lassen. Wenn Sie absolut startklar sind, können Sie die Software PhoneGap verwenden, um Ihre Webanwendung in eine native iPhone App zu konvertieren und sie an den App Store zu senden. Sollte sie ultimativ abgelehnt werden, ist das Projekt nicht tot, denn Sie können immer noch die Web-App anbieten. Wenn sie genehmigt wird, umso besser! Sie können dann anfangen, die App mit Funktionen zu erweitern, die die grandiosen Hardwarefunktionen des Geräts nutzen. Das klingt wie das Beste aus beiden Welten, oder?
Wer sollte dieses Buch lesen? Ich gehe davon aus, dass Sie grundlegende Erfahrungen im Lesen und Schreiben von HTML, CSS und JavaScript (insbesondere jQuery) haben. In den Kapiteln 5 und 6 werde ich einige grundlegende SQL-Quelltexte verwenden, eine flüchtige Kenntnis von SQL wäre also hilfreich, ist aber nicht zwingend erforderlich.
Was brauchen Sie, um mit diesem Buch zu arbeiten? Dieses Buch wird das iPhone SDK vermeiden, wo immer es geht. Alles was Sie brauchen, um bei der großen Mehrheit der Beispiele mitzukommen, ist ein Texteditor und die aktuellste Version von Safari (oder noch besser WebKit, das eine innovativere Version von
X | Vorwort
Safari ist und sowohl für Mac OS als auch für Windows unter http://webkit.org zur Verfügung steht). In Kapitel 7 brauchen Sie dann einen Mac für PhoneGap. Dort erkläre ich, wie man Ihre Webanwendung in eine native App konvertiert, die Sie dann im App Store veröffentlichen können.
Konventionen in diesem Buch Die folgenden drucktechnischen Konventionen werden in diesem Buch verwendet: Kursiv Kennzeichnet neue Ausdrücke, URLs, E-Mail-Adressen, Dateinamen und Dateiendungen. Konstante Breite
Wird für Programmlistings und innerhalb von Absätzen für den Verweis auf Programmelemente, wie Variablen- oder Funktionsnamen, Datenbanken, Datentypen, Umgebungsvariablen, Ausdrücke und Schlüsselwörter, verwendet. Konstante Breite, fett
Zeigt Befehle oder sonstigen Text an, der vom Anwender wörtlich eingegeben werden soll, und wird für Hervorhebungen innerhalb von Programmlistings verwendet. Konstante Breite, kursiv
Markiert Text, der durch anwenderbezogene Werte ersetzt werden soll, die sich aus dem Kontext ergeben. Dieses Symbol kennzeichnet Tipps, Hinweise oder generelle Anmerkungen.
Dieses Symbol zeigt eine Warnung an.
Codebeispiele verwenden Dieses Buch ist dazu da, Sie darin zu unterstützen, Ihre Arbeit zu tun. Im Allgemeinen dürfen Sie die Quelltexte aus diesem Buch in Ihren Programmen und Dokumentationen nutzen. Sie brauchen uns nicht um Erlaubnis fragen, solange Sie keine erhebliche Menge an Code reproduzieren. Wenn Sie beispielsweise ein Programm schreiben, das Teile der Beispiele aus diesem Buch verwendet, brauchen Sie keine Genehmigung. Sollten Sie allerdings eine CD-ROM mit Beispielen aus O’Reilly-Büchern verkaufen oder verteilen, wird eine Erlaubnis benötigt. Das Beantworten von Fragen durch das Zitieren von Texten oder Listings aus diesem Buch ist ohne Genehmigung möglich. Sie brauchen aber eine
Vorwort |
XI
Erlaubnis, wenn Sie große Teile dieses Buchs in die Dokumentation Ihres Produkts einfließen lassen. Wir begrüßen Quellenangaben, setzen sie aber nicht voraus. Quellenangaben beinhalten üblicherweise den Titel sowie Autor, Verlag und die ISBN, zum Beispiel: iPhone Apps mit HTML, CSS und JavaScript von Jonathan Stark. Copyright 2010 O’Reilly Verlag, 978-3-89721-603-7. Wenn Sie denken, Ihr Gebrauch der Programmbeispiele fiele nicht in die oben abgegebene Genehmigung, können Sie uns gern unter [email protected] kontaktieren.
Danksagung Ein Buch zu schreiben, ist Teamarbeit. Mein herzlicher Dank für ihren großzügigen Beitrag geht an die folgenden Personen: Tim O’Reilly, Brian Jepson und den Rest der ORM-Truppe, die meine Buchschreibeerfahrungen so lohnend und lehrreich machten. Jack Templin, Providence Geeks und RI Nexus, die mich in die blühende Technologieszene meiner Heimatstadt einführten. Dieses Buch würde nicht existieren, wenn es Providence Geeks nicht gäbe. David Kandeda für sein zwanghaftes Streben nach Schönheit. Egal ob es sich um ein Stück Code oder eine Benutzeroberflächenanimation handelt, er kann nicht schlafen, bis es perfekt ist. Ich finde das toll. Brian LeRoux, Brock Whitten, Rob Ellis und den Rest der Nitobi-Truppe für das Schreiben und die weiterführende Betreuung von PhoneGap. Brian Fling für die Erweiterung meines Horizonts in Sachen Mobilgeräte über die neueste und beste Hardware hinaus. Brian kennt sich seit Beginn damit aus; er ist ein wunderbarer Autor und darüber hinaus ein sehr großherziger Kerl. PPK, John Gruber, John Allsopp und John Resig für ihren Beitrag zu und ihre Unterstützung bei den zugrunde liegenden Technologien, die dieses Buch möglich machten. Garrett Murray, Brian LeRoux und den Schwarm von Menschen, die freigiebig Kommentare und Fragen auf der OFPS-Seite zu diesem Buch geschrieben haben. Eure Rückmeldungen waren sehr hilfreich und sehr willkommen. Kazu, Chuckie, Janice, Chris und den Rest der Haruki-Truppe, die so nachsichtig waren, als ich endlos in voller Lautstärke vor mich hin getippt habe. Meine wunderbare Familie, Freunde und Kunden, weil sie so verständnisvoll und hilfsbereit waren, während ich an die Tastatur gefesselt war. Und schließlich Erica. Du machst alles möglich. Ich liebe dich!
XII | Vorwort
Kapitel 1
KAPITEL 1
Los geht’s
Bevor wir eintauchen und damit beginnen, Anwendungen für das iPhone zu entwickeln, würde ich gern das Spielfeld definieren. In diesem Kapitel werde ich die grundsätzlichen Bedingungen festlegen, die Vor- und Nachteile der beiden gebräuchlichsten Herangehensweisen an die Entwicklung vergleichen und einen Crashkurs für die drei grundlegenden Webtechniken, die in diesem Buch verwendet werden, präsentieren.
Web-Apps im Vergleich zu nativen Apps Zuerst einmal definiere ich, was ich mit einer »Web-App« und einer »nativen App« meine. Anschließend werde ich jeweils die Vor- und Nachteile abwägen.
Was ist eine Web-App? Für mich ist eine Web-App im Wesentlichen eine Website, die speziell für das iPhone optimiert wurde. Diese Website kann alles sein, von einer Standardbroschüre eines kleinen Unternehmens über einen Zinsrechner bis hin zu einem täglichen Kalorienzähler – der Inhalt spielt keine Rolle. Die entscheidenden Merkmale einer Web-App sind, dass die Benutzeroberfläche mit Standard-Webtechnologien erstellt wurde, dass sie über eine URL ansprechbar ist (öffentlich, privat oder versteckt hinter einem Log-in) und dass sie speziell auf die Besonderheiten des iPhone optimiert wurde. Eine Web-App wird weder auf dem iPhone installiert, noch ist sie im App Store verfügbar, und sie ist auch nicht in Objective-C geschrieben.
Was ist eine native App? Im Gegensatz dazu werden native Anwendungen auf dem iPhone installiert, haben Zugriff auf die Hardware (Lautsprecher, Beschleunigungssensoren, Kamera usw.), und sie sind in Objective-C programmiert. Allerdings ist das sie auszeichnende Merkmal, dass
| 1
sie im iTunes App Store verfügbar ist – eine Besonderheit, die die Fantasie von Horden von Softwareunternehmern, mich eingeschlossen, angeregt hat.
Vor- und Nachteile Unterschiedliche Apps haben unterschiedliche Anforderungen. Manche Apps passen besser zu Webtechnologien als andere. Wenn Sie die Vor- und Nachteile der verschiedenen Ansätze kennen, fällt es Ihnen leichter, für Ihre Situation den richtigen Weg auszuwählen. Dies sind die Vorteile der Entwicklung von nativen Apps: • Millionen von registrierten Kreditkartenbesitzern sind nur einen Klick entfernt. • Xcode, Interface Builder und das Cocoa Touch Framework bilden zusammen eine schicke Entwicklungsumgebung. • Sie können die ganzen coolen Hardwarefunktionen des Geräts nutzen. Und hier sind die Nachteile der Entwicklung von nativen Apps: • Sie müssen bezahlen, um ein Apple-Entwickler zu werden. • Sie müssen sich der Gnade des Überprüfungsprozesses von Apple unterwerfen. • Sie müssen in Objective-C programmieren. • Sie müssen auf einem Mac entwickeln. • Sie können Fehlerbehebungen nicht zügig veröffentlichen. • Der Entwicklungszyklus ist langsam, und der Testzyklus ist durch den App Store beschränkt. Dies sind die Vorteile der Entwicklung von Web-Apps: • Webentwickler können ihre bisherigen Entwicklerprogramme nutzen. • Sie können ihre aktuellen Webdesign- und Programmierfähigkeiten nutzen. • Sie sind bei der Entwicklung nicht auf Mac OS angewiesen. • Ihre App läuft auf jedem Gerät mit einem Webbrowser. • Sie können Fehler sofort beheben. • Der Entwicklungszyklus ist schnell. Das sind die Nachteile der Entwicklung von Web-Apps: • Sie können die coolen iPhone-Hardwarefunktionen nicht nutzen. • Sie müssen sich selbst um ein Abrechnungssystem kümmern, wenn Sie mit der App Geld verdienen möchten. • Es kann schwierig werden, anspruchsvolle Effekte für die Benutzeroberfläche zu erstellen.
2 |
Kapitel 1: Los geht’s
Welcher Ansatz ist für Sie der richtige? Ab hier wird es nun spannend. Dadurch dass das iPhone ständig online ist, schafft es eine Umgebung, in der die Grenzen zwischen Web-Apps und nativen Apps verschwimmen. Es gibt ein paar weniger bekannte Funktionen im iPhone, die es Ihnen ermöglichen, Web-Apps auch offline zu nutzen (siehe Kapitel 6). Darüber hinaus entwickeln einige Fremdanbieter Software – von denen PhoneGap die bemerkenswerteste ist –, mit denen Webentwickler eine Web-App nehmen und sie als native App für das iPhone und andere mobile Plattformen verpacken können. Für mich ist das die perfekte Mischung. Ich kann in meiner »Mutterprogrammiersprache« schreiben, das Produkt als reine Web-App veröffentlichen (für das iPhone und andere Geräte, die einen mobilen Browser haben), ohne mich durch Apples Überprüfungsprozess zu quälen. Außerdem kann ich denselben Quelltext als Grundlage dazu verwenden, um eine erweiterte native Version zu erstellen, die dann die Hardwarefunktionen des Geräts nutzt und möglicherweise auch im App Store verkauft werden kann. Und wenn Apple die App ablehnt? Kein Thema, weil ich immer noch meine Onlineversion habe. Ich kann weiter an der nativen Version arbeiten, während die Kunden die Web-App nutzen.
Crashkurs in Webprogrammierung Die drei Technologien, die wir hauptsächlich für die Entwicklung von Web-Apps nutzen werden, sind HTML, CSS und JavaScript. Ich möchte gern jede von ihnen kurz abhandeln, um sicherzugehen, dass wir auf dem gleichen Stand sind, wenn wir uns auf die ausgefallenen Sachen stürzen.
Einführung in HTML Wenn Sie im Internet surfen, sind die Seiten, die Sie sehen, einfache Textdokumente auf einem fremden Computer. Der Text einer typischen Webseite wird in HTML-Tags gesteckt, die Ihrem Browser etwas über die Struktur der Seite verraten. Mit diesen Informationen kann der Browser entscheiden, wie er den Seiteninhalt am sinnvollsten anzeigen kann. Betrachten wir einmal den HTML-Schnipsel in Beispiel 1-1. In der ersten Zeile wird die Zeichenfolge Hallo! von einem Paar h1-Tags umschlossen. (Beachten Sie, dass das öffnende Tag und das schließende Tag etwas unterschiedlich sind: Das schließende Tag hat als zweites Zeichen einen Schrägstrich, während das öffnende Tag ohne auskommt.) Indem man einen Text mit h1-Tags umgibt, sagt man dem Browser, dass die eingeschlossenen Wörter eine Überschrift (engl. headline) sind. Der Browser wird sie dann in großer, fetter Schrift in einer eigenen Zeile anzeigen. Es gibt auch h2-, h3-, h4-, h5- und h6-Tags. Je
Crashkurs in Webprogrammierung | 3
kleiner die Zahl ist, umso wichtiger ist die Überschrift. Eine h6-Überschrift wird also kleiner (weniger wichtig aussehend) dargestellt als eine h3-Überschrift. Hinter den h1-Tags in Beispiel 1-1 kommen zwei Zeilen, die von p-Tags umschlossen sind. Das sind sogenannte Absatz-Tags (engl. paragraph). Browser stellen jeden Absatz in einer eigenen Zeile dar. Wenn der Absatz lang genug ist, um das Ende des Browserfensters zu erreichen, wird er automatisch umbrochen und in der nächsten Zeile fortgesetzt. In jedem Fall wird aber eine Leerzeile hinter dem Absatz eingefügt, um ihn vom nächsten Element auf der Seite zu trennen. Beispiel 1-1: HTML-Schnipsel
Hallo!
Danke, dass du meine Homepage besuchst.
Ich hoffe, du magst sie.
Sie können HTML-Tags auch innerhalb anderer HTML-Tags verwenden. Beispiel 1-2 zeigt eine ungeordnete Liste (ul-Tag, vom engl. »unordered list«), die drei Listenelemente (li-Tags, vom engl. »list item«) enthält. In einem Browser würde die Liste mit Aufzählungspunkten vor jedem Listeneintrag erscheinen. Wenn man Tags innerhalb von anderen Tags betrachtet, spricht man von Kinder-Tags bzw. Kindern des Eltern-Tags. In diesem Beispiel sind die li-Tags also Kinder des Eltern-Tags ul. Beispiel 1-2: Ungeordnete Liste
Pizza
Bier
Hotdogs
Die Tags, die ich bisher gezeigt habe, sind allesamt Block-Tags. Ein Block-Tag zeichnet sich dadurch aus, dass es in einer eigenen Zeile, ohne Elemente links oder rechts daneben, angezeigt wird. Deshalb erweitern Überschriften, Absätze und Listenelemente die Seite immer nach unten und nicht nach rechts. Das Gegenteil eines Block-Tags ist ein Inline-Tag, das, wie der Name schon sagt, innerhalb einer Zeile auftauchen kann. Das Betonungs-Tag (em-Tag, vom engl. »emphasis«) ist ein Beispiel für so ein Inline-Tag und sieht folgendermaßen aus:
Ich hoffe <em>wirklich, dass Sie es mögen.
Der Großvater der Inline-Tags – und wohl die coolste Funktion in HTML – ist das a-Tag. Es steht für Anker (engl. »anchor«), aber ich werde dieses Tag auch als Link oder Hyperlink bezeichnen. Der Text, der in a-Tags eingebettet ist, wird anklickbar, so dass ein Klick darauf den Browser dazu bringt, eine neue HTML-Seite zu laden. Um dem Browser zu sagen, welche neue Seite geladen werden soll, müssen wir dem Tag etwas hinzufügen, das man Attribut (oder Eigenschaft) nennt. Attribute sind benannte Werte, die in ein öffnendes Tag eingefügt werden. In einem Anker-Tag verwendet man
4 |
Kapitel 1: Los geht’s
Umlaute in HTML Die deutschen Umlaute und das ß werden in HTML besonders behandelt. Man ersetzt sie durch diese Zeichenfolgen: Sonderzeichen
Ersetzung
Sonderzeichen
Ersetzung
ä
ä
Ü
Ü
ö
ö
ß
ß
ü
ü
>
>
Ä
Ä
<
<
Ö
Ö
&
&
Wie Sie sehen, müssen auch < und >, die ja für HTML-Tags reserviert sind, und das &Zeichen, das von den Ersetzungen selbst verwendet wird, ersetzt werden.
das Attribut href, um die Adresse der Zielseite anzugeben. Hier folgt ein Link auf die Google-Homepage: Google
Das mag ein wenig durcheinander erscheinen, wenn Sie noch nicht mit dem Lesen von HTML vertraut sind, aber Sie können sicher die Google-URL darin erkennen. Sie werden in diesem Buch eine Menge a-Tags finden. Nehmen Sie sich also ruhig einen Moment Zeit, um das im Kopf zu verarbeiten, sollte es Sie auf den ersten Blick noch etwas verwirren. Es gibt einige Dinge, die man zu Attributen im Hinterkopf behalten sollte. Verschiedene HTML-Tags erlauben unterschiedliche Attribute. Man kann in einem öffnenden Tag mehrere Eigenschaften definieren, indem man sie durch Leerzeichen voneinander trennt. Ein schließendes Tag kann keine Attribute enthalten. Es gibt Hunderte von möglichen Tag-Attribut-Kombinationen, aber keine Panik, wir werden uns in diesem Buch nur mit etwa einem Dutzend beschäftigen.
Der HTML-Schnipsel, den wir betrachtet haben, würde normalerweise im body-Bereich eines kompletten HTML-Dokuments vorkommen. Ein HTML-Dokument besteht aus zwei Bereichen: dem Kopf (engl. »head«) und dem Körper bzw. Rumpf (engl. »body«). Im Körper legen Sie alle Informationen ab, die der Anwender später sehen soll. Der Kopf enthält dagegen Informationen über die Seite, von denen die meisten für den Betrachter unsichtbar sind. Kopf und Körper werden immer zusammen von html-Tags umschlossen. Beispiel 1-3 zeigt den Schnipsel im Kontext eines ordentlichen HTML-Dokuments. Der head-Bereich umfasst hier nur ein title-Element, das dem Browser verrät, welcher Text in der Titelleiste des Fensters angezeigt werden soll.
Crashkurs in Webprogrammierung | 5
Beispiel 1-3: Ein ordentliches HTML-Dokument Meine tolle Seite
Hallo!
Danke, dass du meine Homepage besuchst.
Ich hoffe, du magst sie.
Pizza
Bier
Hotdogs
Wenn Sie Ihren Browser verwenden, betrachten Sie normalerweise Seiten, die im Internet abgelegt sind. Browser sind aber genauso gut dazu geeignet, HTML-Dokumente zu betrachten, die auf Ihrem lokalen Computer liegen. Um zu sehen, was ich meine, öffnen Sie einen Texteditor und tippen Beispiel 1-3 ab. Speichern Sie es anschließend als test. html auf dem Schreibtisch ab. Öffnen Sie die Datei dann mit Safari, indem Sie sie entweder auf das Safari-Programmsymbol ziehen oder Safari öffnen und dann ABLAGE → DATEI ÖFFNEN auswählen. Ein Doppelklick auf test.html könnte auch funktionieren, aber es könnte sich auch ein Texteditor oder ein anderer Browser öffnen, wenn Sie das vorher eingestellt haben. Selbst wenn Sie nicht unter Mac OS X arbeiten, sollten Sie Ihre iPhoneWeb-Apps in Safari testen, denn Safari ist der Desktop-Browser, der dem mobilen Safari auf dem iPhone am nächsten kommt. Safari für Windows steht unter http://www.apple.de/safari/ zum Download bereit.
Einige Texteditoren sind nicht wirklich gut zum Schreiben von HTML geeignet. Sie sollten insbesondere Editoren meiden, die Rich-Text bearbeiten können, wie zum Beispiel Microsoft Word oder TextEdit. Solche Editoren können ihre Dateien in anderen Formaten als reinem Text abspeichern, was Ihr HTML zerstören wird. Wenn Sie auf der Suche nach einem guten Texteditor sind, verrate ich Ihnen meinen mit Abstand liebsten Editor für den Mac: TextMate (http://macromates.com/). Ich habe gehört, dass es einen Windows-Klon gibt, der »E Text Editor« heißt (http://www.e-texteditor.com). Wenn Sie es lieber kostenlos mögen, können Sie Text Wrangler für den Mac herunterladen (http://www.barebones.com/products/TextWrangler/) oder unter Windows den mitgelieferten Editor Notepad nutzen.
6 |
Kapitel 1: Los geht’s
Einführung in CSS Wie Sie gesehen haben, stellen Browser bestimmte HTML-Elemente mit individuellen Formatierungen dar (Überschriften sind groß und fett, auf Absätzen folgt eine Leerzeile und so weiter). Diese Formatierungen sind sehr einfach und in erster Linie dazu gedacht, dem Leser zu helfen, die Struktur und die Aussage des Dokuments zu verstehen. Um über diese auf einer sehr einfachen Struktur basierende Darstellung hinauszugehen, können Sie Cascading Style Sheets (CSS) verwenden. CSS ist eine Layoutsprache, die genutzt wird, um die visuelle Darstellung eines Dokuments zu definieren. Sie können CSS verwenden, um einfache Dinge, wie Textfarbe, Schriftgröße und Schriftstil (fett, kursiv usw.), oder komplexe Sachen, wie Seitenlayout, Farbverläufe, Deckkraft und vieles mehr, zu definieren. Beispiel 1-4 zeigt eine CSS-Regel, die den Browser anweist, jeden Text im body-Element in Rot anzuzeigen. In diesem Beispiel ist body der Selektor (engl. selector; gibt an, was von der Regel verändert werden soll), und die geschweiften Klammern umschließen die Deklaration (die Regel selbst). Die Deklaration beinhaltet einen Satz von Eigenschaften mit ihren Werten. In diesem Beispiel ist color die Eigenschaft und red der Wert der Eigenschaft. Beispiel 1-4: Eine einfache CSS-Regel body { color: red; }
Die Namen der Eigenschaften sind in den CSS-Spezifikationen vordefiniert, das heißt, dass Sie diese nicht einfach selbst erfinden können. Jede Eigenschaft erwartet einen passenden Wert, und es kann tatsächlich viele passende Werte oder Wertformate für eine bestimmte Eigenschaft geben. Sie können zum Beispiel eine Farbe durch ein vordefiniertes Schlüsselwort (red) oder durch die Verwendung der HTML-Farbcodenotation (#FF0000) angeben. Dabei wird die hexadezimale Notation verwendet: Drei Paare von hexadezimalen Ziffern (0–F) repräsentieren (von links nach rechts) die Werte für Rot, Grün und Blau. Eigenschaften, die Maße erwarten, akzeptieren Werte, wie 10px, 75% und 1em. Beispiel 1-5 zeigt einige typische Deklarationen. (Der verwendete Farbcode für background-color entspricht dem CSS-Wert für Grau: gray.) Beispiel 1-5: Einige übliche CSS-Deklarationen body { color: red; background-color: #808080; font-size: 12px; font-style: italic; font-weight: bold; font-family: Arial; }
Crashkurs in Webprogrammierung | 7
Es gibt viele verschiedene Arten von Selektoren. Wenn Sie alle Hyperlinks (a-Elemente) kursiv darstellen wollten, würden Sie die folgende Zeile in Ihre CSS einfügen: a { font-style: italic; }
Möchten Sie speziell nur die Links kursiv darstellen, die sich innerhalb eines h1-Tags befinden, würden Sie diese Zeile Ihrer CSS hinzufügen: h1 a { font-style: italic; }
Sie können auch eigene Selektoren definieren, indem Sie die Attribute id und/oder class Ihren HTML-Tags hinzufügen:
Hallo!
Danke, dass du meine Homepage besuchst.
Ich hoffe, du magst sie.
Pizza
Bier
Hotdogs
Hätte ich nun .loud { font-style: italic; } der CSS-Datei dieser HTML-Datei hinzugefügt, wären Hallo! und Pizza kursiv dargestellt worden, da sie beide die Klasse loud besitzen. Der Punkt vor der .loud-Klasse ist wichtig. Dadurch weiß CSS, dass es nach Tags mit der Klasse loud Ausschau halten muss. Wenn Sie den Punkt vergessen, würde CSS nach loud-Tags suchen, die in diesem Schnipsel nicht existieren (bzw. in HTML überhaupt, nebenbei bemerkt). CSS-IDs verhalten sich ähnlich. Um dem highlight-Absatz einen gelben Hintergrund hinzuzufügen, würden Sie diese Regel verwenden: #highlight { background-color: yellow; }
Hier steht das #-Symbol dafür, dass CSS nach einem HTML-Tag mit der ID highlight suchen muss. Fassen wir noch einmal zusammen: Sie können Elemente entweder über den Tag-Namen (zum Beispiel body, h1, p), über den Klassennamen (zum Beispiel .loud, .subtle, .error) oder über die ID (zum Beispiel #highlight, #login, #promo) auswählen. Außerdem können Sie spezifischer werden, indem Sie Selektoren verketten (zum Beispiel h1 a, body ul .loud). Es gibt Unterschiede zwischen class und id. Die class-Eigenschaft sollte verwendet werden, wenn Sie mehrere Elemente auf der Seite haben, die den gleichen class-Wert haben. Umgekehrt gilt, dass id-Werte für die Seite einmalig sein müssen. Aufgrund dieser Tatsache entschloss ich mich, einfach immer class-Eigenschaften zu verwenden, damit ich mir keine Sorgen darüber machen muss, ob ich vielleicht einen id-Wert doppelt vergeben habe. Allerdings ist die Auswahl von id-Elementen deutlich schneller als die über class. Deshalb kann die Performance deutlich leiden, wenn Sie zu viele class-Selektoren verwenden.
8 |
Kapitel 1: Los geht’s
Nun verstehen Sie die Grundlagen von CSS. Aber wie verknüpft man eine CSS-Datei mit einer HTML-Datei? Das ist eigentlich ganz einfach. Man verlinkt die CSS-Datei im headBereich des HTML-Dokuments, wie in Beispiel 1-6 gezeigt. Die href-Eigenschaft in diesem Beispiel ist ein relativer Pfad, was bedeutet, dass sie auf eine Textdatei namens screen.css im selben Verzeichnis verweist, in dem auch die HTML-Datei liegt. Sie können aber ebenfalls absolute Links angeben, zum Beispiel: http://beispiel.de/screen.css
Beispiel 1-6: Eine CSS-Datei einbinden Meine tolle Seite
Hallo!
Danke, dass du meine Homepage besuchst.
Ich hoffe, du magst sie.
Pizza
Bier
Hotdogs
Beispiel 1-7 zeigt den Inhalt der Datei screen.css. Sie sollten die Datei im selben Ordner abspeichern, in dem auch die HTML-Datei liegt. Beispiel 1-7: Eine einfache CSS-Datei body { font-size: 12px; font-weight: bold; font-family: Arial; } a { font-style: italic; } h1 a { font-style: italic; } .loud { font-style: italic; } #highlight { background-color: yellow; }
Der Vollständigkeit halber sei gesagt, dass man theoretisch auch auf CSSDateien verweisen kann, die auf anderen Servern abgelegt sind. Allerdings könnte es als sehr unhöflich aufgefasst werden, wenn Sie ohne Erlaubnis auf eine fremde CSS-Datei verweisen, also binden Sie bitte nur Ihre eigenen Dateien ein.
Crashkurs in Webprogrammierung | 9
Für einen schnellen und gründlichen CSS-Crashkurs empfehle ich wärmstens CSS kurz & gut von Eric Meyer (O’Reilly). Wenn es um CSS geht, hat Eric das letzte Wort, und dieses besondere Buch ist kurz genug, um es während des morgendlichen Wegs zur Arbeit mit Ihrer Fahrgemeinschaft zu lesen ... solange Sie nicht der Fahrer sind, in diesem Fall könnte es etwas länger dauern (sagte ich »Crash«-Kurs?).
Einführung in JavaScript An diesem Punkt sollten Sie wissen, wie man ein Dokument mit HTML strukturiert und wie man seine visuelle Darstellung per CSS verändert. Nun werden wir etwas JavaScript hinzufügen, damit es auch etwas ausführen kann. JavaScript ist eine Skriptsprache, die einer HTML-Datei hinzugefügt werden kann, um sie interaktiver und benutzerfreundlicher zu machen. So können Sie zum Beispiel JavaScript nutzen, um während der Eingabe in ein Formular zu prüfen, ob die eingegebenen Daten gültig sind. Oder Sie können JavaScript Elemente zeigen oder verstecken lassen, je nachdem, wohin der Anwender klickt. Außerdem kann JavaScript den Webserver ansprechen, um Datenbankänderungen auszuführen, ohne dass die Seite neu geladen werden muss. Wie jede moderne Skriptsprache hat JavaScript Variablen, Felder (Arrays), Objekte und all die typischen Kontrollstrukturen (if, while, for usw.). Beispiel 1-8 zeigt einen JavaScript-Schnipsel, der einige Kernkonzepte der Sprache verdeutlicht. Beispiel 1-8: Grundlegende JavaScript-Syntax var foods = ['Äpfel', 'Bananen', 'Orangen']; 1 for (var i in foods) { 2 if (foods[i] == 'Äpfel') { 3 alert(foods[i] + ' sind meine Lieblingsfrüchte!'); 4 } else { alert(foods[i] + ' sind ganz in Ordnung.'); 5 } }
Hier ist Folgendes passiert: 1 Ein Array namens food wird definiert, das drei Elemente besitzt. 2 Hier wird eine Schleife gestartet, die die Variable i definiert, die während der Schleife den Index für jedes Element beinhaltet. 3 Eine gewöhnliche if-Abfrage prüft, ob das aktuelle Element gleich Äpfel ist. 4 Das wird ausgegeben, wenn das aktuelle Element des Arrays gleich Äpfel ist. 5 Das wird ausgegeben, wenn das aktuelle Element des Arrays nicht gleich Äpfel ist.
10 | Kapitel 1: Los geht’s
Und dies sind einige erwähnenswerte Punkte zur JavaScript-Syntax: • Ausdrücke werden mit einem Semikolon beendet. • Codeblöcke werden mit geschweiften Klammern umschlossen. • Variablen werden mit dem Schlüsselwort var definiert. • Array-Elemente werden über die Eckige-Klammern-Notation angesprochen. • Array-Schlüssel werden beginnend mit 0 zugeordnet. • Das einfache Gleichheitszeichen ist der Zuweisungsoperator. • Das doppelte Gleichheitszeichen ist der logische Gleichheitsoperator. • Das Pluszeichen ist der String-Verknüpfungsoperator. Für unsere Zwecke ist der wichtigste Aspekt von JavaScript, dass es mit den Elementen einer HTML-Seite interagieren kann (coole Kids nennen es »das DOM manipulieren«). Beispiel 1-9 zeigt ein einfaches Stück JavaScript, das einen Text auf der Seite ändert, wenn der Anwender auf die h1-Überschrift klickt. DOM steht für Document Object Model und repräsentiert in diesem Zusammenhang, wie der Browser eine HTML-Seite versteht. Hier können Sie mehr über das DOM erfahren: http://de.wikipedia.org/wiki/Document_ Object_Model. Beispiel 1-9: Ein einfacher OnClick-Handler Meine tolle Seite <script type="text/javascript" charset="utf-8"> 1 function sayHello() { 2 document.getElementById('foo').innerHTML = 'Hallo!'; 3 } 4 5
Klick mich!
Folgendes ist passiert: 1 Ich habe dem Kopf des HTML-Dokuments einen script-Block hinzugefügt. 2 In dem script-Block habe ich eine einfache JavaScript-Funktion namens sayHello() definiert. 3 Die Funktion sayHello() beinhaltet einen einzigen Ausdruck, der dem Browser sagt: »Suche im Dokument nach einem Element mit der ID ›foo‹ und setze dessen innerHTML-Wert auf ›Hallo!‹.« Der Effekt im Browser ist, dass der Text »Klick mich!« durch »Hallo!« ersetzt wird, sobald der Anwender auf das h1-Element klickt.
Crashkurs in Webprogrammierung
| 11
4 Hier endet die Funktion sayHello(). 5 Der script-Block endet hier. 6 Das Attribut onclick des h1-Elements sagt dem Browser, dass er etwas tun soll, falls der Anwender auf die Überschrift klickt, nämlich die Funktion sayHello() auszuführen. Damals, in der schlechten alten Zeit der Webentwicklung, hatten unterschiedliche Browser verschiedene JavaScript-Unterstützungen. Das bedeutete, dass Ihr Programm zwar in Safari 2, aber nicht im Internet Explorer 6 laufen würde. Sie mussten also ganz schön leiden und das Programm in jedem Browser (und auch in verschiedenen Versionen des gleichen Browsers) testen, um sicherzustellen, dass es überall läuft. Als dann die Zahl der Browser und der Browserversionen wuchs, wurde es schlicht unmöglich, ein Programm für alle Umgebungen zu testen. In jener Zeit war es echt die Hölle, Webprogrammierung mit JavaScript durchzuführen. Kommen wir zu jQuery. jQuery ist eine relativ kleine JavaScript-Bibliothek, die es Ihnen erlaubt, Ihren JavaScript-Quelltext so zu schreiben, dass er in einer großen Vielfalt von Browsern auf die gleiche Weise funktioniert. Hinzu kommt, dass es einige typische Webentwickleraufgaben wunderbar vereinfacht. Aus diesem Grund nutze ich jQuery für den Großteil meiner Entwicklungsarbeit, und ich werde es für die JavaScript-Beispiele in diesem Buch verwenden. Beispiel 1-10 ist die jQuery-Version von Beispiel 1-9. Beispiel 1-10: Der onClick-Handler in der jQuery-Version Meine tolle Seite <script type="text/javascript" src="jquery.js"> 1 <script type="text/javascript" charset="utf-8"> function sayHello() { $('#foo').text('Hallo!'); 2 }
Klick mich!
1 Hier füge ich die Bibliothek jquery.js ein. Ich habe einen relativen Pfad verwendet, was bedeutet, dass die Datei im selben Ordner liegt wie die HTML-Datei. Ich hätte sie aber genauso gut von diversen anderen Orten einbinden können, an denen sie verfügbar ist. 2 Beachten Sie, wie viel weniger Code wir brauchen, um den Austausch des Texts im h1-Element vorzunehmen. Das mag in so einem trivialen Beispiel nicht nach einer großen Sache aussehen, aber ich kann Ihnen versichern, dass es in komplexen Lösungen eine Art Lebensretter bedeutet .
12 | Kapitel 1: Los geht’s
Wir werden noch jede Menge jQuery-Code im echten Einsatz sehen. Deshalb lasse ich das hier erst einmal so stehen. jQuery-Download, -Dokumentationen und -Einführungen sind unter http:// jquery.com erhältlich. Um jQuery nutzen zu können, müssen Sie es von der Website herunterladen, die Datei (so etwas wie jquery-1.3.2.min.js) in jquery.js umbenennen und eine Kopie in das Verzeichnis der HTML-Datei legen.
Crashkurs in Webprogrammierung
| 13
Kapitel 2
KAPITEL 2
Einfaches iPhone-Styling
Letztendlich wollen wir eine native iPhone-App mit HTML, CSS und JavaScript entwickeln. Der erste Schritt auf diesem Weg ist, sich damit vertraut zu machen, wie man HTML-Seiten so aufbessert, dass sie wie eine iPhone-App aussehen. In diesem Kapitel werde ich Ihnen zeigen, wie man CSS einem Bündel von existierenden HTML-Seiten hinzufügt, damit man sie einfach auf einem iPhone bedienen kann. Sie werden damit nicht nur ihrem Ziel näher kommen, eine eigene native App zu bauen, sondern auch eine praktische (und wertvolle) Fähigkeit erlernen, die Sie sofort einsetzen können.
Sie haben keine Website? Wenn Sie Ihre Webseiten bisher immer lokal auf Ihrem Computer getestet haben, werden Sie sie so nicht auf dem iPhone testen können. Dazu müssen Sie einen Server aufsetzen. Sie haben die Wahl: • Legen Sie Ihre Webseiten auf einem Webserver ab (Ihr Internetdienstanbieter unterhält eventuell einen Web-Hosting-Service) und verbinden Sie sich mit dem iPhone mit diesem Server. • Legen Sie Ihre Webseiten auf einem Webserver ab, der auf Ihrem Computer läuft, und verbinden Sie sich mit Ihrem iPhone mit dem Server. Das funktioniert nur, wenn Ihr iPhone das gleiche WLAN-Netzwerk wie der Computer nutzt. • Wenn Sie kein iPhone besitzen, können Sie eines in Safari simulieren. Aktivieren Sie dazu einfach in den erweiterten Einstellungen das ENTWICKLER-Menü, wählen Sie dann ENTWICKLER → BENUTZER-AGENT und suchen Sie dort die gewünschte Version des mobilen Safari aus, die simuliert werden soll. Dieses Kapitel ist so aufgebaut, dass Sie die Beispiele beim Lesen direkt ausprobieren können. Egal, welche Möglichkeit Sie gewählt haben, um Ihre Webseiten zu betrachten: laden Sie sie einfach im Browser (vorzugsweise im iPhone-Browser) neu, wenn Sie etwas Neues den Beispieldateien hinzugefügt und diese abgespeichert haben.
| 15
Erste Schritte Theorie ist großartig, aber ich bin eher der »Zeig’s mir, rede nicht nur drüber«-Typ. Los geht’s! Stellen Sie sich vor, Sie haben eine Webseite, die Sie iPhone-isieren wollen (Abbildung 2-1). In diesem Szenario gibt es einige einfache Dinge, mit denen Sie die Site für das iPhone optimieren können. Diese Möglichkeiten werde ich Ihnen in diesem Kapitel vorstellen.
Abbildung 2-1: Die Desktop-Version einer typischen Webseite sieht im Safari auf einem Computer gut aus.
Abbildung 2-2 zeigt, wie dieselbe Webseite auf einem iPhone aussieht. Im Normalfall ist sie weit davon entfernt, optimal zu sein.
Abbildung 2-2: Dieselbe Seite sieht auf dem iPhone ganz okay aus, aber wir können das Aussehen deutlich verbessern.
16 | Kapitel 2: Einfaches iPhone-Styling
Beispiel 2-1 zeigt eine verkürzte (und übersetzte) Version der HTML-Seite aus Abbildung 2-1. Das ist die HTML-Datei, mit der Sie in diesem Kapitel arbeiten werden. Sie können sie auf der Webseite zum Buch herunterladen, wenn Sie das Styling selbst ausprobieren möchten, während Sie sich durch das Kapitel arbeiten. Die Desktop-Stylesheet-Datei (screen.css) ist nicht abgedruckt, da sie nicht wichtig ist, aber Sie können die CSS-Datei aus dem letzten Kapitel verwenden, wenn Sie ein wenig damit herumspielen möchten. Beispiel 2-1: Das HTML-Dokument, das wir stylen werden Jonathan Stark
Jonathan Stark ist ein Webentwickler, Redner und Autor. Seine Beratungsfirma, Jonathan Stark Consulting, Inc., hat Kunden wie Staples, Turner Broadcasting und die PGA Tour gewonnen. ...
Jonathan Stark ist ein Entwickler für mobile und Webapplikationen, den das Wall Street Journal einen Experten in der Veröffentlichung von Desktop-Daten im Web genannt hat.
Über Jahre hinweg haben Entwickler Tabellen verwendet, um Elemente an einem Gitter auszurichten. Die Weiterentwicklungen von CSS und HTML haben dieses Verfahren nicht nur überflüssig, sondern sogar unerwünscht werden lassen. Heute nutzt man hauptsächlich das div-Element (im Zusammenspiel mit einer Vielzahl an Attributen), um die gleiche Aufgabe zu bewältigen, allerdings mit mehr Kontrolle. Obwohl eine umfassende Behandlung von div-basierten Layouts den Umfang dieses Buchs deutlich sprengen würde, werden Sie viele Beispiele dazu sehen, während Sie die Kapitel lesen. Wenn Sie mehr lernen möchten, empfehle ich Ihnen Webdesign mit Webstandards von Jeffrey Zeldman (Addison-Wesley), das sich diesem Thema intensiv widmet.
Vorbereitung eines separaten iPhone-Layouts Ich bin ein großer Verfechter des DRY-Konzepts (siehe den folgenden Hinweis), aber im echten Leben ist man besser dran, wenn man einen klaren Schnitt zwischen dem Desktop-Browser-Layout und dem iPhone-Layout macht. Vertrauen Sie auf mein Wort und legen Sie zwei komplett unterschiedliche CSS-Dateien an – Sie werden besser schlafen. Die Alternative wäre, alle CSS-Regeln in ein einziges Layout zu zwängen, was sich aus mehreren Gründen als eine ganz schlechte Idee herausstellen würde; der offensichtlichste ist, dass Sie eine Menge unnützer Desktop-Layout-Regeln an das iPhone senden und damit wertvolle Bandbreite und Speicher verschwenden würden. DRY steht für »wiederhole dich nicht« (engl.: Don’t Repeat Yourself) und ist ein Prinzip aus der Softwareentwicklung, das aussagt: »Jedes Stück Wissen muss eine einzige, eindeutige, verbindliche Verköperung innerhalb eines Systems haben.« Dieser Begriff wurde von Andrew Hunt und David Thomas in ihrem Buch Der Pragmatische Programmierer (Hanser Fachbuch) geprägt.
Um das Layout für das iPhone zu definieren, ersetzen Sie das link-Tag im BeispielHTML-Dokument mit den beiden folgenden Ausdrücken:
18 | Kapitel 2: Einfaches iPhone-Styling
Hier verweist desktop.css auf Ihr bestehendes Desktop-Layout, und iphone.css ist eine neue Datei, die wir gleich im Detail besprechen werden. Wenn Sie dieses Beispiel mit dem früher gezeigten HTML-Dokument nachvollziehen, müssen Sie die Datei screen.css in desktop.css umbenennen; da wir uns aber auf das iPhone-Layout konzentrieren werden, können Sie das Desktop-Layout auch einfach ignorieren. Sollte es nicht geladen werden können, wird sich der Browser schon nicht zu sehr aufregen.
Bedauerlicherweise wird der Internet Explorer die obigen Anweisungen nicht verstehen. Deshalb müssen wir einen Bedingungskommentar (hier fett gedruckt) einfügen, der auf eine spezielle IE-Version der CSS verweist:
Gut, nun ist es an der Zeit, das HTML-Dokument zu bearbeiten: Löschen Sie den existierenden Link auf die Datei screen.css und ersetzen Sie sie durch die gerade gezeigten Zeilen. Auf diese Weise können Sie mit der iPhone-spezifischen CSS-Datei, die ich in diesem Kapitel zeigen werde, noch einmal frisch anfangen.
Die Seitengröße einstellen Solange Sie ihm nichts anderes sagen, geht Safari davon aus, dass Ihre Seite 980px breit ist (Abbildung 2-3). Im Großteil der Fälle funktioniert das gut. Allerdings wollen Sie unsere Inhalte speziell für das kleinere Display des iPhone formatieren. Deshalb müssen Sie Safari das wissen lassen, indem Sie ein meta-Tag mit dem Namen viewport (engl. für Darstellungsfeld) in das head-Element des HTML-Dokuments einfügen: <meta name="viewport" content="user-scalable=no, width=device-width" />
Wenn Sie die Breite nicht setzen, wird die Seite beim ersten Laden sehr weit herausgezoomt sein. Das meta-Tag viewport wird von allen anderen Browsern mit Ausnahme des mobilen Safari ignoriert. Deshalb können Sie es einfügen, ohne sich über die Desktop-Version Ihrer Seite Sorgen zu machen.
Allein durch das Unterdrücken des Desktop-Layouts und durch das Einstellen des Darstellungsfelds haben Sie den iPhone-Anwendern zu einer besseren Sicht auf Ihre Seite verholfen (Abbildung 2-4). Um sie nun wirklich zu beeindrucken, lassen Sie uns mit dem Aufbau des iphone.css-Stylesheets beginnen.
Erste Schritte
| 19
Abbildung 2-3: Das iPhone unterstellt einer normalen Webseite eine Breite von 980px.
Abbildung 2-4: Durch das Festlegen des Darstellungsbereichs auf die Breite des Geräts wird Ihre Seite deutlich lesbarer.
Die iPhone-CSS hinzufügen Es gibt einige Richtlinien für die Benutzeroberfläche (auch »UI« genannt vom engl. »user interface«), die eine iPhone-App wie eine iPhone-App aussehen lassen. Im nächsten Abschnitt werde ich die markante Titelleiste, Listen mit abgerundeten Ecken, fingerfreundliche Links, die wie glänzende Buttons aussehen, und Weiteres hinzufügen. Verwenden Sie Ihren Texteditor, um eine Datei namens iphone.css zu erstellen und den Code aus Beispiel 2-2 einzufügen. Speichern Sie diese Datei im selben Ordner ab, in dem auch das HTML-Dokument liegt.
20 | Kapitel 2: Einfaches iPhone-Styling
Beispiel 2-2: Hier werden einige Website-übergreifende Styles über das HTML-body-Element festgelegt body { background-color: #ddd; color: #222; font-family: Helvetica; font-size: 14px; margin: 0; padding: 0; }
/* Hintergrundfarbe */ /* Textfarbe */
/* rundum frei bleibender Bereich außerhalb von body */ /* rundum frei bleibender Bereich innerhalb von body */
Beachten Sie, dass ich die Schrift für das Dokument generell auf Helvetica gesetzt habe, da sie von den meisten Apps auf dem iPhone genutzt wird. Wenn Sie der App ein professionelles Aussehen geben möchten, sollten Sie möglichst bei Helvetica bleiben, solange Sie keinen triftigen Grund zu einer Änderung haben.
Nun werde ich das div-Element mit dem Namen header angehen in dem der HauptHome-Link (zum Beispiel der Logo-Link) sowie die primäre und sekundäre Navigation enthalten sind. Der erste Schritt ist, den Logo-Link als klickbare Titelleiste zu formatieren. Fügen Sie den folgenden Code in die Datei iphone.css ein: #header h1 { margin: 0; padding: 0; } #header h1 a { background-color: #ccc; border-bottom: 1px solid #666; color: #222; display: block; font-size: 20px; font-weight: bold; padding: 10px 0; text-align: center; text-decoration: none; }
Ich werde die ul-Blocks der primären und sekundären Navigation identisch formatieren, so dass ich den allgemeinen Element-Selektor (zum Beispiel #header ul) anstelle der Element-IDs (zum Beispiel #header ul#utility, #header ul#nav) nutzen kann. #header ul { list-style: none; margin: 10px; padding: 0; } #header ul li a { background-color: #FFFFFF; border: 1px solid #999999; color: #222222;
Bis jetzt ganz einfach, oder? Mit diesem Stückchen CSS haben wir schon eine starke Verbesserung des iPhone-Seitendesigns bewirkt (Abbildung 2-5): #content, #sidebar { padding: 10px; }
Abbildung 2-5: Schon ein bisschen CSS kann die Bedienbarkeit der Seite auf dem iPhone ein großes Stück nach vorne bringen. Sie wundern sich vielleicht, warum ich den padding-Wert für die div-Elemente #content und #sidebar angepasst habe und warum ich das nicht gleich global im body-Element gemacht habe. Der Grund ist, dass es häufig vorkommt, dass Elemente bis an den Rand reichen sollen (wie zum Beispiel die Titelleiste in diesem Beispiel). Deshalb würde ein padding-Wert ungleich null im body-Element, oder in jedem anderen seitenübergreifenden Element, mehr Ärger machen als nötig.
Als Nächstes setzen Sie noch etwas den padding-Wert für die div-Elemente #content und #sidebar, um den Text ein wenig vom Bildschirmrand wegzurücken (Abbildung 2-6). Der Inhalt des div-Elements footer ist auf dieser Seite quasi eine Wiederholung des Navigationselements oben auf der Seite (das ul-Element mit der ID nav). Sie können den Footer in der iPhone-Version also getrost ausblenden, indem Sie folgende Zeilen in die Datei iphone.css einfügen:
22 | Kapitel 2: Einfaches iPhone-Styling
#footer { display: none; }
Abbildung 2-6: Der Text wird vom Rand weggerückt.
iPhone-Look-and-Feel hinzufügen Zeit, noch etwas schicker zu werden. Fangen wir oben auf der Seite an und fügen wir einen 1 Pixel breiten weißen Schlagschatten zum Text des Logo-Links und einen CSSFarbverlauf zum Hintergrund hinzu: #header h1 a { text-shadow: 0px 1px 0px #fff; background-image: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#999)); }
In der text-shadow-Deklaration sind die Parameter von links nach rechts: horizontaler Abstand, vertikaler Abstand, Unschärfe und Farbe. Meist werden Sie genau diese Werte Ihren Texten zuweisen, denn das sieht auf einem iPhone nun einmal gut aus. Es macht trotzdem Spaß, mit text-shadow herumzuspielen, denn es kann Ihrem Design einen subtilen, aber raffinierten Touch verleihen. Die Zeile -webkit-gradient verdient besondere Beachtung. Sie ist eine Anweisung an den Browser, im laufenden Betrieb ein Farbverlaufbild zu erstellen. Deshalb kann ein CSSFarbverlauf überall verwendet werden, wo man normalerweise im CSS-Code url() verwenden würde (zum Beispiel Hintergrundbild, Listenbilder). Die Parameter sind von links nach rechts: Farbverlauftyp (kann linear oder radial sein), Startpunkt des Farbverlaufs (mögliche Werte: left top, left bottom, right top, right bottom), Endpunkt des Farbverlaufs, Startfarbe, Endfarbe.
iPhone-Look-and-Feel hinzufügen | 23
Achten Sie darauf, dass Sie die horizontale Position (left, right) vor der vertikalen Position (top, bottom) schreiben und sie nicht vertauschen. Mit anderen Worten: top left, bottom left, top right und bottom right sind unzulässige Werte.
Der nächste Schritt ist, dem Navigationsmenü die traditionellen abgerundeten Ecken zu verpassen: #header ul li:first-child a { -webkit-border-top-left-radius: 8px; -webkit-border-top-right-radius: 8px; } #header ul li:last-child a { -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; }
Wie Sie sehen können, nutze ich die für die Ecken spezifischen Versionen der -webkitborder-radius-Eigenschaft, um einen 8px-Radius für die beiden oberen Ecken des ersten Listenelements und die unteren zwei Ecken des letzten Listenelements zu definieren (Abbildung 2-7).
Abbildung 2-7: Farbverläufe, Textschatten und abgerundete Ecken sind der Anfang für die Transformation Ihrer Website in eine App mit nativem iPhone-Look.
Es wäre zwar cool, wenn man die abgerundeten Ecken direkt für das umschließende ulElement definieren könnte, aber das funktioniert nicht. Wenn Sie es ausprobieren, werden Sie sehen, dass die harten Ecken der Listenelemente die runden Ecken der Liste überlagern und somit den Effekt aufheben.
24 | Kapitel 2: Einfaches iPhone-Styling
Technisch gesehen, könnte man den Effekt der abgerundeten Ecken auf das ul-Element anwenden, wenn man dessen Hintergrundfarbe auf Weiß und die Hintergrundfarbe der Listenelemente transparent setzen würde. Allerdings würde bei einem Klick auf das obere oder untere Listenelement dieses blau hinterlegt, und diese Farbe würde die runden Ecken überlagern, was fürchterlich aussieht. Das beste Verfahren ist, die Ecken den Listenelementen selbst zuzuweisen, wie ich es hier demonstriert habe.
Elementares Verhalten mit jQuery hinzufügen Einer der Hauptgründe für den Spaß, den ich habe, wenn ich Web-Apps für das iPhone entwickle, ist, dass ich mich darauf verlassen kann, dass JavaScript aktiviert ist (was nicht immer der Fall sein muss, wenn man Websites für Desktop-Browser entwickelt). Ich werde unsere Beispielseite nun mit etwas JavaScript versehen, um einige elementare iPhone-typische Funktionalitäten zu unterstützen. Insbesondere möchte ich den Anwendern ermöglichen, den großen, auffälligen Navigationsbereich oben ein- und auszublenden, so dass sie ihn nur sehen, wenn sie wollen. Damit das funktioniert, werde ich noch ein paar neue CSS-Anweisungen schreiben und etwas JavaScript hinzufügen, um das neue CSS zum existierenden HTML hinzuzufügen. Lassen Sie uns zuerst einen Blick auf den neuen CSS-Teil werfen. Schritt eins ist, die ulElemente zu verstecken, damit sie beim ersten Laden der Seite nicht auftauchen. Wenn Sie zu Hause mitmachen, öffnen Sie bitte die Datei iphone.css und fügen folgende Zeilen ein: #header ul.hide { display: none; }
Als Nächstes werde ich den Stil der Schaltfläche definieren, die das Menü ein- und ausblenden soll. Beachten Sie, dass sie noch nicht im HTML-Dokument existiert. Nur zur Information: Der Button wird in HTML so definiert werden:
Menü
Ich werde in Kürze auf das HTML für den Button genauer eingehen (Seite 27), kümmern Sie sich also erst einmal nicht weiter darum. Es ist nur wichtig zu wissen, dass es sich um ein div-Element mit der Klasse leftButton handelt, das in der Titelleiste platziert werden soll. Hier kommt das CSS-Layout für den Button (das Sie gleich in Ihre Datei iphone.css übernehmen können): #header div.leftButton { position: absolute;1 top: 7px; left: 6px; height: 30px;2
Für die im Folgenden verwendeten Grafiken können Sie die aus dem jQTouch-Paket nehmen. Laden Sie dazu jQTouch von http://jqtouch.com/ herunter und kopieren Sie die Grafiken aus dem Verzeichnis themes/jqt/img in Ihren images-Unterordner für das HTML-Dokument (legen Sie das Verzeichnis images an, falls es noch nicht existiert). Wir werden jQTouch im Detail in Kapitel 4 besprechen.
1 Fangen wir oben an, wo ich die Position als absolute definiert habe, um das div-Element aus dem Dokumentenfluss zu nehmen. Das erlaubt mir, dessen Pixelkoordinaten für oben und links zu definieren. 2 Hier setze ich die Höhe auf 30px, damit der Button groß genug ist, um bequem darauf tippen zu können. 3 Als Nächstes setze ich den Text fett und weiß, versehe ihn mit einem leichten Schlagschatten und zentriere ihn im div-Element. 4 In CSS ist die Funktion rgb() eine Alternative zur üblichen Hex-Notation, um Farben anzugeben (zum Beispiel #FFFFFF). rgb(255, 255, 255) und rgb(100%, 100%, 100%) sind beide mit #FFFFFF gleichzusetzen. Vor kurzem wurde noch die Funktion rgba() eingeführt, die es erlaubt, einen vierten Parameter anzugeben, der den Alphawert (Deckkraft) der Farbe angibt. Der Bereich der gültigen Werte befindet sich zwischen 0 und 1, wobei 0 vollkommen transparent und 1 völlig deckend bedeutet; Dezimalbrüche zwischen 0 und 1 werden transluzent (Milchglaseffekt) dargestellt. 5 Das Setzen von line-height sorgt dafür, dass der Text im div-Element vertikal nach unten geschoben wird und nicht an die obere Kante stößt. 6 Die Zeilen mit border-width und -webkit-border-image müssen ein wenig erklärt werden. Diese beiden Eigenschaften zusammen ermöglichen es, Bereiche eines einzelnen Bilds dem Randbereich eines Elements zuzuordnen. Das bedeutet, dass man sich hier endlich div-Elemente ohne Texte und das Zerschneiden von Grafiken in topLeftCorner.png, topRightCorner.png und so weiter sparen kann. Wenn sich das div-Element vergrößert, weil der Text länger ist, wird sich das Randbild automatisch strecken, um das zu kompensieren. Dies ist wirklich richtig klasse: Weniger Bilder bedeuten weniger Arbeit, weniger Bandbreitennutzung und kürzere Ladezeiten. In der border-width-Zeile sage ich dem Browser, dass er oben einen Rand von 0px, rechts von 8px, unten von 0px und links einen Rand von 8px setzen soll (die vier Para-
26 | Kapitel 2: Einfaches iPhone-Styling
meter starten oben und gehen dann im Uhrzeigersinn weiter). Beachten Sie, dass weder border-style noch border-color für den Rand gesetzt werden muss. 7 Nachdem border-width definiert ist, kann ich nun das -webkit-border-image setzen. Die fünf Parameter sind von links nach rechts: die URL des Bilds, die obere Breite, die rechte Breite, die untere Breite und die linke Breite (wieder im Uhrzeigersinn von oben). Die URL kann absolut (http://beispiel.de/myBorderImage.png) oder relativ sein. Relative Pfade beziehen sich auf den Speicherort der CSS-Datei, nicht auf den der HTML-Datei, die die CSS-Datei nachlädt. Als ich mich zum ersten Mal mit webkit-border-image beschäftigte, fand ich es seltsam, dass ich die Randbreiten definieren musste, obwohl ich das schon mit border-width getan hatte. Nach einigen schmerzvollen Testversuchen fand ich heraus, dass die Breiten der Eigenschaft webkit-borderimage keine Randbreiten sind, sondern die Breiten der Stücke, die vom Bild abgeschnitten werden sollen. Nehmen wir den rechten Rand als Beispiel, dann sage ich dem Browser, er soll die rechten 8 Pixel des Bilds nehmen und sie dem rechten Rand zuordnen, der ebenfalls 8 Pixel breit ist. Es ist durchaus möglich, hier etwas vermeintlich Sinnloses zu tun, wie zum Beispiel die rechten 4 Pixel eines Bilds einem 20-Pixel-Rand zuzuordnen. Damit das ordentlich funktioniert, muss man optionale Parameter in webkit-border-image setzen, um dem Browser zu sagen, was er mit dem Bildstückchen in dem zur Verfügung stehenden freien Platz machen soll (repeat, stretch, round usw.). In drei Jahren des Testens ist mir kein irrwitziger Grund eingefallen, warum man das tun sollte. Deshalb werde ich hier keinen Platz verschwenden, um diese verwirrende und unpraktische Option eines ansonsten hervorragenden Features zu beschreiben.
Okay, Zeit für etwas JavaScript. Zur Vorbereitung der JavaScripts, die Sie gleich schreiben werden, müssen Sie das HTML-Dokument erweitern, um die Dateien jquery.js und iphone.js einzubinden. Fügen Sie diese beiden Zeilen (in genau dieser Reihenfolge) in den head-Bereich Ihrer HTML-Datei ein: <script type="text/javascript" src="jquery.js"> <script type="text/javascript" src="iphone.js">
jQuery-Download, -Dokumentationen und -Einführungen sind unter http:// jquery.com erhältlich. Um jQuery nutzen zu können, müssen Sie es von der Website herunterladen, die Datei (so etwas wie jquery-1.3.2.min.js) in jquery.js umbenennen und eine Kopie in das Verzeichnis der HTML-Datei legen.
Der Hauptzweck des JavaScripts, das wir schreiben müssen, ist es, dem Anwender zu erlauben, das Navigationsmenü ein- und auszublenden. Kopieren Sie das folgende JavaScript in eine neue Datei, die Sie iphone.js nennen und im selben Ordner abspeichern, in dem die HTML-Datei liegt.
1 Der gesamte Code ist von einem if-Ausdruck umschlossen, um sicherzustellen, dass die Eigenschaft innerWidth des window-Objekts existiert (sie existiert in einigen Versionen des Internet Explorer nicht) und dass die Breite kleiner oder gleich 480px ist (die maximale Breite des iPhone). Mit dieser Zeile stellen wir sicher, dass der JavaScript-Code nur ausgeführt wird, wenn der Anwender die Seite mit einem iPhone, oder mit einem Gerät ähnlicher Größe, betrachtet. Wenn Sie Ihre iPhone-Webseiten mit einem Desktop-Safari testen, wie es im Kasten »Sie haben keine Website?« auf Seite 15 beschrieben ist, wird die if-Abfrage hier fehlschlagen, wenn die Browserbreite zu groß ist. Als Behelfslösung können Sie die folgende JavaScript-Zeile in die Adresszeile eingeben, um dem Browser eine etwas iPhone-gerechtere Größe zu verpassen: javascript:window.scrollTo(0,0);resizeTo(320,480);
Sie können das Höhenmaß auch noch vergrößern, um eine hohe und schlanke Ansicht zu erzeugen, was manchmal hilfreich ist, wenn man mit viel Content arbeitet (wie später in Abbildung 2-10 gezeigt).
2 Hier haben wir die sogenannte »document ready«-Funktion. Wenn jQuery für Sie Neuland ist, mag das ein wenig einschüchternd aussehen, und ich gestehe, dass ich eine Weile gebraucht habe, um mir die Syntax zu merken. Allerdings ist es die Zeit wert, sich die Funktion ins Gedächtnis zu brennen, denn Sie werden sie oft verwenden. Die »document ready«-Funktion sagt eigentlich nur: »Wenn das Dokument fertig ist, führe diesen Code aus.« Mehr dazu, warum das wichtig ist, in einer Sekunde. 3 Dies ist typischer jQuery-Code, der damit anfängt, die ul-Elemente im div-Element mit der ID header auszuwählen und ihnen die CSS-Klasse hide hinzuzufügen. Wie Sie sich erinnern werden, ist hide der Selektor, den wir im CSS-Code weiter oben verwendet haben. Unterm Strich kommt bei der Ausführung dieser Zeile heraus, dass die ul-Elemente im div-Bereich mit der ID header versteckt werden. Hier noch ein besonderer Hinweis: Wenn wir die Zeile nicht in die »document ready«-Funktion geschrieben hätten, würde sie eventuell ausgeführt, bevor die ul-Elemente fertig geladen wären. Das bedeutet, dass das JavaScript während des Ladens der Seite fehl-
28 | Kapitel 2: Einfaches iPhone-Styling
schlüge, da die ul-Elemente noch gar nicht existierten. Wenn die Seite dann weiter lüde, würden die ul-Elemente erscheinen, und Sie würden sich am Kopf kratzen (oder Ihre Tastatur wegschmeißen) und sich wundern, warum das JavaScript nicht funktioniert. d Hier füge ich die Schaltfläche in die Titelleiste ein, die es dem Anwender ermöglicht, das Menü ein- und auszublenden (Abbildung 2-8). Sie hat eine Klasse .leftButton, für die wir schon eine CSS-Regel erstellt haben, und sie besitzt einen onclick-Handler, der die Funktion toggleMenu() aufruft, die als Nächstes kommt.
Abbildung 2-8: Die Menüschaltfläche wurde per jQuery dynamisch zur Titelleiste hinzugefügt.
5 Die Funktion toggleMenu() verwendet die jQuery-Funktion toggleClass(), um eine spezielle Klasse in einem Objekt hinzuzufügen oder zu entfernen. In dieser Zeile schalte ich die hide-Klasse der ul-Elemente im div-Element mit der ID header an und aus. 6 Hier schalte ich die pressed-Klasse der Schaltfläche leftButton an und aus. Wir haben die CSS-Regel für die pressed-Klasse noch nicht geschrieben. Lassen Sie uns das nachholen. Öffnen Sie die Datei iphone.css und fügen Sie die folgenden Zeilen ein: #header div.pressed { -webkit-border-image: url(images/button_clicked.png) 0 8 0 8; }
Wie Sie sehen können, gebe ich einfach ein anderes Bild für den Button-Rand an (es ist ein wenig dunkler). Das fügt der Schaltfläche einen Zwei-Zustände-Effekt hinzu, der dem Anwender verständlich macht, dass derselbe Button das Menü sowohl anzeigen als auch ausblenden kann (Abbildung 2-9).
Elementares Verhalten mit jQuery hinzufügen | 29
Abbildung 2-9: Der Menü-Button wird dunkler, wenn er gedrückt wurde, um das Menü anzuzeigen.
Abbildung 2-10: Eine lang gezogene Ansicht der kompletten iPhone-CSS.
Was Sie gelernt haben In diesem Kapitel habe ich die Grundlagen der Konvertierung einer existierenden Webseite in ein iPhone-freundlicheres Format gezeigt. Ich habe ein wenig dynamisches HTML verwendet, um die Navigation ein- und auszublenden. Im nächsten Kapitel werde ich auf diesen Beispielen aufbauen, indem ich einige fortgeschrittene JavaScript-Konzepte einführen werde – nämlich ein paar echte Ajax-Leckerbissen.
30 | Kapitel 2: Einfaches iPhone-Styling
Kapitel 3
KAPITEL 3
Fortgeschrittenes iPhone-Styling
In unserer Mission, eine iPhone-App ohne Objective-C zu erstellen, haben wir bisher gelernt, wie wir eine Sammlung von HTML-Seiten mit CSS so aussehen lassen wie eine iPhone-App. In diesem Kapitel werden wir die Grundlagen dafür legen, dass dieselben Seiten sich auch so verhalten wie eine iPhone-App. Wir werden besprechen, wie man Ajax nutzt, um eine komplette Website in eine Eine-Seiten-App zu verwandeln, wie man einen Zurück-Button mit Verlauf per JavaScript erzeugt und wie man das Webclip-Icon und den Vollbildmodus des iPhone dazu verwendet, die App starten zu lassen, ohne dass sich der mobile Safari in das Anwendungserlebnis einmischt.
Ein wenig Ajax hinzufügen Der Begriff Ajax ist so ein Modewort geworden, dass ich nicht mehr sicher bin, ob ich noch weiß, was es bedeutet. Für die Zwecke dieses Buchs meine ich mit Ajax eine Technik, die JavaScript nutzt, um Anfragen an einen Webserver zu stellen, ohne die aktuelle Seite neu zu laden (zum Beispiel um etwas HTML zu empfangen, ein Formular abzusenden und Ähnliches). Dieser Ansatz sorgt für ein sehr geschmeidiges Anwendererlebnis, setzt aber voraus, dass man einige Räder neu erfindet. Wenn Sie beispielsweise externe Seiten dynamisch nachladen, gibt der Browser keinen Hinweis auf den Fortschritt oder auf Fehler an den Anwender. Darüber hinaus wird der Zurück-Button nicht wie erwartet funktionieren, es sei denn, Sie unternehmen allerlei Anstrengungen, um ihn zu unterstützen. Mit anderen Worten: Man muss eine Menge Arbeit erledigen, um eine nette Ajax-App zu erstellen. Trotzdem gibt es ein paar gute Gründe, sich die Mühe zu machen. Vor allem öffnet sich dadurch die Tür zum Erstellen von iPhone-Apps, die im Vollbildmodus (»Vollbildmodus« auf Seite 51) und sogar offline (Kapitel 6) laufen.
| 31
Verkehrspolizist Für meine nächste Beispielserie werde ich eine einzelne Seite namens iphone.html schreiben, die vor allen anderen Seiten sitzt und Anfragen behandelt – wie eine Art Verkehrspolizist. Und so funktioniert es: Beim ersten Laden präsentiert iphone.html dem Anwender eine schön formatierte Version der Seitennavigation. Dann werde ich jQuery verwenden, um onclick-Aktionen zu »entführen«, so dass die Navigationslinks nicht eine neue Seite im Browser öffnen. Stattdessen wird jQuery ein wenig HTML von der anderen Seite laden und die Daten an den Anwender weitergeben, indem es die aktuelle Seite aktualisiert. Ich werde mit der Version des Codes für die einfachste Funktionalität beginnen und sie dann Schritt für Schritt erweitern. Die HTML-Anweisungen für die Vorschaltdatei iphone.html ist ganz simpel (siehe Beispiel 3-1). Im head-Bereich setze ich title und viewport. Außerdem binde ich ein Layout (iphone.css) und zwei JavaScript-Dateien ein: jquery.js und eine eigene JavaScript-Datei namens iphone.js. Mehr Informationen über jquery.js, wo es sie gibt und was man damit macht, gibt es im Abschnitt »Einführung in JavaScript« auf Seite 10.
Im body-Bereich gibt es zwei div-Elemente: eines mit der ID header für den ersten Titel in einem h1-Tag und ein leeres div-Element, in das wir später HTML von anderen Seiten hineinladen werden. Beispiel 3-1: Diese einfache HTML-Vorschaltseite wird sich vor alle anderen Seiten der Website drängeln Jonathan Stark <meta name="viewport" content="user-scalable=no, width=device-width" /> <script type="text/javascript" src="jquery.js"> <script type="text/javascript" src="iphone.js">
Jonathan Stark
Machen wir weiter mit der Datei iphone.css. Wie Sie in Beispiel 3-2 sehen können, habe ich einige Eigenschaften aus früheren Beispielen zusammengemischt (zum Beispiel sind einige der Eigenschaften für #header h1 hoch in den Bereich #header gerutscht). Alles in allem sollte es Ihnen aber vertraut vorkommen (falls nicht, schlagen Sie bitte noch einmal in Kapitel 2 nach).
32 | Kapitel 3: Fortgeschrittenes iPhone-Styling
Beispiel 3-2: Die grundlegende CSS-Datei ist eine leicht neu gemischte Version aus früheren Beispielen. body { background-color: #ddd; color: #222; font-family: Helvetica; font-size: 14px; margin: 0; padding: 0; } #header { background-color: #ccc; background-image: -webkit-gradient(linear, left top, left bottom, from(#ccc), to(#999)); border-color: #666; border-style: solid; border-width: 0 0 1px 0; } #header h1 { color: #222; font-size: 20px; font-weight: bold; margin: 0 auto; padding: 10px 0; text-align: center; text-shadow: 0px 1px 0px #fff; } ul { list-style: none; margin: 10px; padding: 0; } ul li a { background-color: #FFF; border: 1px solid #999; color: #222; display: block; font-size: 17px; font-weight: bold; margin-bottom: -1px; padding: 12px 10px; text-decoration: none; } ul li:first-child a { -webkit-border-top-left-radius: 8px; -webkit-border-top-right-radius: 8px; } ul li:last-child a { -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; } ul li a:active,ul li a:hover { background-color:blue;
Verkehrspolizist | 33
Beispiel 3-2: Die grundlegende CSS-Datei ist eine leicht neu gemischte Version aus früheren Beispielen (Fortsetzung). color:white; } #content { padding: 10px; text-shadow: 0px 1px 0px #fff; } #content a { color: blue; }
Alle Magie dieses Beispiels passiert im JavaScript in der Datei iphone.js. Bitte schauen Sie sich Beispiel 3-3 an, während ich Zeile für Zeile durchgehe. Dieses JavaScript lädt ein Dokument namens index.html und wird nicht ohne dieses funktionieren. Sie sollten die HTML-Datei aus Kapitel 2 wiederverwenden und sicherstellen, dass Sie es mit dem Namen index.html im selben Ordner abspeichern, in dem Sie auch die iphone.html aus diesem Kapitel abgelegt haben. Allerdings wird keiner der Links in index.html funktionieren, wenn die jeweiligen Zielseiten nicht existieren. Sie können die Seiten selbst anlegen oder den Beispielcode von der Seite zum Buch herunterladen (siehe »Codebeispiele verwenden« auf Seite XI). Wenn Sie die Dateien about.html, blog.html und consulting-clinic.html anlegen, haben Sie einige Links zum Spielen. Dazu müssen Sie einfach die Datei index.html einige Male duplizieren und danach umbenennen. Um den Effekt zu verstärken, können Sie die jeweiligen h2-Elemente verändern, damit sie zur Datei passen (zum Beispiel in der blog.html:
Blog
). Beispiel 3-3: Dieses bisschen JavaScript in der Datei iphone.js ändert jeden Link auf der Seite in eine Ajax-Anfrage $(document).ready(function(){ 1 loadPage(); }); function loadPage(url) {2 if (url == undefined) { $('#container').load('index.html #header ul', hijackLinks);3 } else { $('#container').load(url + ' #content', hijackLinks);4 } } function hijackLinks() {5 $('#container a').click(function(e){6 e.preventDefault();7 loadPage(e.target.href);8 }); }
1 Hier verwende ich die »document ready«-Funktion, damit der Browser die Funktion loadPage() aufruft, sobald das DOM komplett ist.
34 | Kapitel 3: Fortgeschrittenes iPhone-Styling
2 Die Funktion loadPage() akzeptiert einen einzigen Parameter namens url und prüft dann (in der nächsten Zeile), ob ein Wert gesendet wurde. 3 Wenn kein Wert in die Funktion gesendet wurde, wird url undefiniert sein, und diese Zeile wird ausgeführt. Diese und die folgenden Zeilen sind Beispiele für die Funktion load() von jQuery. Diese Funktion ist exzellent dazu geeignet, kurz und schmerzlos Ajax-Funktionalität zu einer Seite hinzuzufügen. Wenn die Zeile ins Deutsche übersetzt würde, stünde da: »Nimm alle ul-Elemente aus dem #header-Element der index.html und füge sie in das #container-Element der aktuellen Seite ein. Wenn du fertig bist, starte die Funktion hijackLinks().« Beachten Sie, dass index. html die Homepage der Website ist. Wenn Ihre Homepage anders heißt, verwenden Sie hier stattdessen deren Dateinamen. 4 Diese Zeile wird ausgeführt, wenn der url-Parameter einen Wert besitzt. Sie besagt: »Nimm das #content-Element der an die Funktion loadPages() übergebenen URL und füge sie in das #container-Element der aktuellen Seite ein. Wenn du damit fertig bist, rufe die Funktion hijackLinks() auf.« 5 Wenn die Funktion load() einmal fertig ist, wird das #container-Element der aktuellen Seite den HTML-Schnipsel enthalten, der empfangen wurde. Danach wird load() die Funktion hijackLinks() aufrufen. 6 In dieser Zeile wird hijackLinks() alle Links im neuen HTML-Dokument finden und mit den nächsten Zeilen einen Click-Handler daran binden. Diesen Click-Handlern wird automatisch ein Ereignisobjekt übergeben, das ich mit dem Funktionsparameter e (engl. event) auslese. Das Ereignisobjekt eines angeklickten Links enthält in e.target.href die URL der fremden Seite. 7 Normalerweise wird ein Webbrowser zu einer neuen Seite springen, sobald ein Link angeklickt wurde. Diese Navigationsweise ist das »Standardverhalten« eines Links. Da wir die Klicks und das Laden von Seiten selbst behandeln wollen, müssen wir dieses Standardverhalten unterbinden. In dieser Zeile habe ich das erledigt, indem ich die eingebaute Methode preventDefault() des Ereignisobjekts aufgerufen habe. Wenn ich diese Zeile ausgelassen hätte, wäre der Browser so pflichttreu gewesen, die aktuelle Seite zu verlassen und zur URL zu springen, die im Link hinterlegt ist. 8 Sobald der Anwender klickt, übergebe ich die URL der fremden Seite an die Funktion loadPage(), und der Zyklus startet erneut. Ich mag an JavaScript besonders, dass man einer Funktion als Parameter eine andere Funktion übergeben kann. Auch wenn das zuerst seltsam aussieht, ist es sehr mächtig und erlaubt es Ihnen, modularen und wiederverwertbaren Code zu schreiben. Wenn Sie mehr darüber wissen möchten, empfehle ich Das Beste an JavaScript von Douglas Crockford (O’Reilly). Tatsächlich sollten Sie sich das Gesamtwerk von Douglas Crockford ansehen, wenn Sie sich mit JavaScript beschäftigen; Sie werden später froh darüber sein.
Verkehrspolizist | 35
Wird die Seite erstmals geladen, werden Click-Handler nicht automatisch ausgeführt; sie werden ausgeführt, wenn der Anwender ein wenig auf der Seite gelesen und sich dann entschieden hat, auf einen Link zu klicken. Das Zuweisen von Click-Handlern ist ein wenig wie das Aufstellen von Sprengfallen; man baut etwas auf, das dann später ausgelöst wird – oder auch nicht. Es ist durchaus sinnvoll, sich ein paar Minuten Zeit zu nehmen, um die Eigenschaften des Ereignisobjekts nachzulesen, das JavaScript in Reaktion auf eine Anwenderaktion im Browser erzeugt. Eine gute Referenz ist unter http://de.selfhtml.org/javascript/objekte/event.htm zu finden.
Ein paar Extras Mit diesem kleinen bisschen HTML, CSS und JavaScript haben wir tatsächlich eine gesamte Website in eine Ein-Seiten-App verwandelt. Allerdings lässt sie noch einige Wünsche offen. Lassen Sie uns das Ganze ein wenig aufpeppen. Da wir dem Browser nicht erlauben, von Seite zu Seite zu springen, bekommt der Anwender keine Rückmeldung über den Fortschritt, während die Daten geladen werden. Wir sollten den Anwender aber irgendwie wissen lassen, dass tatsächlich etwas passiert. Ohne diese Rückmeldung würde sich der Anwender fragen, ob er den Link getroffen oder verfehlt hat, und er würde anfangen, frustriert in der Gegend herumzuklicken. Das kann zu erhöhtem Datentransfer führen und die App instabil werden lassen (bis hin zum Absturz). Wenn Sie diese Web-App in einem lokalen Netzwerk testen, kann die Netzwerkgeschwindigkeit so schnell sein, dass Sie niemals die Laderückmeldung zu Gesicht bekommen. Arbeiten Sie mit Mac OS X, können Sie den gesamten eingehenden Webverkehr verlangsamen, indem Sie ein paar ipfw-Befehle im Terminal eingeben. Diese Kommandos verlangsamen allen Webverkehr beispielsweise auf vier KByte pro Sekunde: sudo ipfw pipe 1 config bw 4KByte/s sudo ipfw add 100 pipe 1 tcp from any to me 80
Wenn Sie den Safari-Desktop-Browser zum Testen der Seiten verwenden, müssen Sie den Hostnamen oder die externe IP-Adresse des Mac in der URL verwenden (zum Beispiel meinmac.local anstelle von localhost). Sind Sie mit den Tests fertig, löschen Sie die Regel mit sudo ipfw delete 100 (Sie können auch alle benutzerdefinierten Regeln mit ipfw flush löschen).
Dank jQuery brauchen wir für diese Art von Rückmeldung nur zwei Zeilen Code. Wir werden einfach ein div-Element mit der Beschriftung »Lade…« in das body-Element einbinden, sobald die Funktion loadPage() aufgerufen wird, und entfernen es wieder, wenn hijackLinks() abgeschlossen ist. Beispiel 3-4 zeigt eine abgewandelte Version von Beispiel 3-3. Die Zeilen, die Sie der Datei iphone.js hinzufügen müssen, sind fett gedruckt.
36 | Kapitel 3: Fortgeschrittenes iPhone-Styling
Beispiel 3-4: Der Seite eine einfache Fortschrittsanzeige hinzufügen $(document).ready(function(){ loadPage(); }); function loadPage(url) { $('body').append('
Beispiel 3-5 zeigt die CSS-Regeln für das div-Element, die der Datei iphone.css hinzugefügt werden müssen. Das Ergebnis können Sie in Abbildung 3-1 sehen.
Abbildung 3-1: Ohne eine Fortschrittsanzeige irgendeiner Art würde die App so erscheinen, als würde sie nicht reagieren, und der Anwender wäre frustriert. Beispiel 3-5: Dieser CSS-Schnipsel wird der Datei iphone.css hinzugefügt, um die Fortschrittsanzeige zu stylen #progress { -webkit-border-radius: 10px; background-color: rgba(0,0,0,.7); color: white;
Ein paar Extras
| 37
Beispiel 3-5: Dieser CSS-Schnipsel wird der Datei iphone.css hinzugefügt, um die Fortschrittsanzeige zu stylen (Fortsetzung) font-size: 18px; font-weight: bold; height: 80px; left: 60px; line-height: 80px; margin: 0 auto; position: absolute; text-align: center; top: 120px; width: 200px; }
Wie Sie im HTML-Quelltext in Kapitel 2 sehen können, haben meine Seiten jeweils eine einzelne h2-Überschrift am Anfang jeder Seite, die einen schönen Seitentitel abgeben würden (Abbildung 3-2). Damit das ein wenig mehr nach iPhone aussieht, werde ich den Titel dort herausnehmen und in die Titelleiste einfügen (Abbildung 3-3). Wieder einmal eilt jQuery zu Hilfe: Sie können einfach drei Zeilen in die Funktion hijackLinks() einfügen, damit das funktioniert. Beispiel 3-6 zeigt die Funktion hijackLinks() mit diesen Änderungen.
Abbildung 3-2: Bevor die Seitenüberschrift in die Titelleiste verschoben wird …
38 | Kapitel 3: Fortgeschrittenes iPhone-Styling
Abbildung 3-3: … und nach dem Verschieben des Seitentitels in die Titelleiste. Beispiel 3-6: Wir verwenden die h2-Überschrift der Zielseite als Beschriftung der Titelleiste function hijackLinks() { $('#container a').click(function(e){ e.preventDefault(); loadPage(e.target.href); }); var title = $('h2').html() || 'Hallo!'; $('h1').html(title); $('h2').remove(); $('#progress').remove(); }
Beachten Sie, dass ich die Titelzeilen vor der Zeile eingefügt habe, die das »Lade…«-Element entfernt. Ich mag es, wenn die Fortschrittsanzeige ganz zuletzt entfernt wird, da sich die Anwendung dann so anfühlt, als würde sie besser reagieren.
Der doppelte senkrechte Strich (||) in der ersten Zeile des eingefügten Codes (fett gedruckt) ist der logisches-oder-Operator. In Deutsch würde sich die Zeile so lesen: »Setze die Variable title auf den HTML-Inhalt des h2-Elements oder auf die Zeichenkette ›Hallo!‹, wenn es kein h2-Element gibt.« Das ist wichtig, weil beim ersten Laden der Seite keine h2-Überschrift existiert, da wir uns nur die ul-Navigationselemente holen. Dieser Punkt sollte vielleicht verdeutlicht werden. Wenn die Anwender erstmals die URL iphone.html laden, sehen sie nur die Seitennavigationselemente anstelle von irgendeinem Seiteninhalt. Sie sehen erst Inhalte, wenn sie einen Link in dieser ersten Navigationsseite anklicken.
Ein paar Extras
| 39
Einige Seiten meiner Website haben Titel, die länger sind und nicht in die Titelleiste passen (Abbildung 3-4). Ich könnte den Text natürlich in mehrere Zeilen umbrechen lassen, aber das wäre nicht sehr iPhone-isch. Stattdessen habe ich das Layout für #header h1 so angepasst, dass lange Texte mit Auslassungspunkten (engl. ellipsis) am Ende abgekürzt werden (siehe Abbildung 3-5 und Beispiel 3-7). Das ist wohl mein CSS-Lieblingsgeheimtrick.
Abbildung 3-4: Zeilenumbrüche in der Titelleiste sind nicht sehr iPhone-isch ...
Abbildung 3-5: ... aber mit Hilfe von CSS-Auslassungspunkten (engl. ellipsis) können wir die Titelleiste besser aussehen lassen.
40 | Kapitel 3: Fortgeschrittenes iPhone-Styling
Beispiel 3-7: Hinzufügen von Auslassungspunkten zu einem Text, der zu lang für sein umschließendes Element ist #header h1 { color: #222; font-size: 20px; font-weight: bold; margin: 0 auto; padding: 10px 0; text-align: center; text-shadow: 0px 1px 0px #fff; max-width: 160px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
Hier kommt der Schnelldurchlauf: max-width: 160px weist den Browser an, dass das h1Element nicht breiter als 160px werden darf. Dann befiehlt overflow: hidden dem Browser, alle Inhalte abzuschneiden, die über die Ränder des Elements hinausragen würden. Als Nächstes hält white-space: nowrap den Browser davon ab, die Zeile in mehrere zu umbrechen. Ohne diese Zeile würde die h1-Überschrift einfach höher werden, um den Text in der vorgegebenen Breite aufnehmen zu können. Bleibt zum Schluss noch textoverflow: ellipsis, um die drei Auslassungspunkte an das Ende des zurechtgeschnittenen Texts zu hängen, um anzuzeigen, dass der Anwender nicht den gesamten Text sieht. Nehmen wir als nächstes einmal an, Sie haben eine »Über mich«-Seite, die länger ist als der sichtbare Bereich beim iPhone. Der Anwender besucht die Seite, scrollt nach unten ans Ende und klickt auf einen Link zur Kontaktseite. Wenn Sie dann eine Kontaktseite haben, die mehr als einen Bildschirm voll Inhalt hat, werden die neuen Daten im Fenster, das immer noch ganz nach unten gescrollt ist, angezeigt. Technisch gesehen, ist das sinnvoll, denn wir verlassen die aktuelle (heruntergescrollte) Seite nicht wirklich, allerdings ist das für den Anwender verwirrend. Um dieses Problem zu lösen, habe ich den Befehl scrollTo() in die Funktion loadPage() eingefügt (siehe Beispiel 3-8). Nun wird jedes Mal, wenn der Anwender auf einen Link klickt, die Seite zuerst nach oben springen. Das hat außerdem den nützlichen Nebeneffekt, dass die Ladegrafik auch dann sichtbar ist, wenn der Anwender einen Link weit unten auf der Seite anklickt. Beispiel 3-8: Es ist besser, wieder nach oben zu scrollen, wenn der Anwender zu einer neuen Seite navigiert function loadPage(url) { $('body').append('
Beispiel 3-8: Es ist besser, wieder nach oben zu scrollen, wenn der Anwender zu einer neuen Seite navigiert (Fortsetzung) $('#container').load(url + ' #content', hijackLinks); } }
Wie die meisten anderen hat auch meine Website Links zu externen Seiten (d.h. Seiten, die auf anderen Domains liegen). Ich möchte diese externen Links nicht entführen, da es keinen Sinn ergibt, deren HTML in mein iPhone-spezifisches Layout zu zwängen. In Beispiel 3-9 habe ich eine Abfrage eingebaut, die die URL auf meinen Domainnamen überprüft. Wenn er gefunden wird, wird der Link entführt und der Inhalt in die aktuelle Seite geladen; da ist Ajax im Einsatz. Falls nicht, wird der Browser normal zur URL navigieren. Sie müssen jonathanstark.com in einen passenden Domain- oder Hostnamen Ihrer Website ändern, oder die Links auf Seiten Ihrer Website werden nicht entführt.
Beispiel 3-9: Man kann es externen Seiten erlauben, normal zu laden, indem man den Domainnamen überprüft function hijackLinks() { $('#container a').click(function(e){ var url = e.target.href; if (url.match(/jonathanstark.com/)) { e.preventDefault(); loadPage(url); } }); var title = $('h2').html() || 'Hallo!'; $('h1').html(title); $('h2').remove(); $('#progress').remove(); }
Die Funktion url.match() verwendet eine Sprache, nämlich reguläre Ausdrücke, die oft in anderen Programmiersprachen wie JavaScript, PHP und Perl eingebettet ist. Auch wenn dieser reguläre Ausdruck einfach ist, können komplexere Ausdrücke ein wenig respekteinflößend sein, es lohnt sich aber, sich mit ihnen vertraut zu machen. Hier finden Sie weitere Informationen dazu: http://de.selfhtml.org/javascript/objekte/regexp.htm.
Ihr eigener Zurück-Button Der größte Klops ist zu diesem Zeitpunkt noch, dass der Anwender keine Möglichkeit hat, zu vorherigen Seiten zurückzunavigieren (wie Sie sich erinnern, haben wir alle Links entführt, und der Verlauf von Safari funktioniert deshalb nicht). Gehen wir die Sache an,
42 | Kapitel 3: Fortgeschrittenes iPhone-Styling
indem wir eine Zurück-Schaltfläche oben links in die Titelleiste einfügen. Zuerst werde ich das JavaScript aktualisieren und mich dann um CSS kümmern. Das Hinzufügen eines normalen iPhone-isierten Zurück-Buttons zu einer App bedeutet, dass man die Klick-Historie des Users im Auge behält. Dafür müssen wir zum einen die URL der vorherigen Seite abspeichern, damit wir wissen, wohin wir zurückspringen sollen, und zum anderen den Titel der vorherigen Seite abspeichern, damit wir den ZurückButton beschriften können. Die Umsetzung dieser Funktionalität hat Auswirkungen auf den Großteil des JavaScripts, das wir bisher geschrieben haben. Deshalb werde ich die komplette neue Version Zeile für Zeile abhandeln (siehe Beispiel 3-10). Das Ergebnis sehen Sie in Abbildung 3-6.
Abbildung 3-6: Ohne glänzenden Pfeil-nach-links-Zurück-Button wäre es keine iPhone-App. Beispiel 3-10: Das existierende JavaScript-Beispiel wird erweitert, um einen Zurück-Button zu unterstützen var hist = [];1 var startUrl = 'index.html';2 $(document).ready(function(){3 loadPage(startUrl); }); function loadPage(url) { $('body').append('
Lade...
');4 scrollTo(0,0); if (url == startUrl) {5 var element = ' #header ul'; } else { var element = ' #content'; } $('#container').load(url + element, function(){6
Ihr eigener Zurück-Button | 43
Beispiel 3-10: Das existierende JavaScript-Beispiel wird erweitert, um einen Zurück-Button zu unterstützen (Fortsetzung) var title = $('h2').html() || 'Hallo!'; $('h1').html(title); $('h2').remove(); $('.leftButton').remove();7 hist.unshift({'url':url, 'title':title});8 if (hist.length > 1) {9 $('#header').append('
'+hist[1].title+'
');j $('#header .leftButton').click(function(){k var thisPage = hist.shift();l var previousPage = hist.shift(); loadPage(previousPage.url); }); } $('#container a').click(function(e){m var url = e.target.href; if (url.match(/jonathanstark.com/)) {n e.preventDefault(); loadPage(url); } }); $('#progress').remove(); }); }
1 In dieser Zeile initialisiere ich eine Variable namens hist als leeres Array. Da ich sie außerhalb von Funktionen definiert habe, existiert sie global und wird überall auf der Seite verfügbar sein. Bitte beachten Sie, dass ich nicht das komplette englische Wort history verwendet habe, da dieses eine vordefinierte Objekteigenschaft in JavaScript ist und in eigenem Code vermieden werden sollte. 2 Hier definiere ich die relative URL der zu ladenden Seite, wenn der Anwender iphone.html zum ersten Mal besucht. Sie haben vielleicht von früheren Beispielen noch im Hinterkopf, dass ich url == undefined geprüft habe, um das erste Laden zu behandeln, aber in diesem Beispiel werden wir an einigen Stellen die Startseite verwenden. Deshalb ist es sinnvoll, sie global zu definieren. 3 Diese und die nächste Zeile bilden die Definition der »document ready«-Funktion. Wie Sie sehen, reiche ich (anders als in früheren Beispielen) die Startseite an die Funktion loadPage() weiter. 4 Weiter geht es mit der Funktion loadPage(). Diese und die nächste Zeile sind unverändert den früheren Beispielen entnommen. 5 Dieser if…else-Ausdruck entscheidet, welches Element von der neuen Seite geladen werden muss. Wenn wir zum Beispiel die Startseite brauchen, nehmen wir die ulElemente aus dem #header-Element; andernfalls nehmen wir das #content-Element. 6 In dieser Zeile sind der URL-Parameter und das dazugehörige Quellelement miteinander zu dem ersten Parameter, der an die Funktion load() übergeben wird,
44 | Kapitel 3: Fortgeschrittenes iPhone-Styling
verknüpft. Als zweiten Parameter übergebe ich eine anonyme Funktion (eine unbenannte Funktion, die direkt an Ort und Stelle ausprogrammiert wird). Wenn wir uns durch diese anonyme Funktion arbeiten, werden Sie sicher eine starke Ähnlichkeit zur Funktion hijackLinks() erkennen, die durch diese anonyme Funktion ersetzt wurde. Die folgenden drei Zeilen sind beispielsweise identisch mit früheren Beispielen. 7 In dieser Zeile entferne ich das Objekt .leftButton von der Seite. (Das mag seltsam wirken, da ich es noch gar nicht eingefügt habe. Das kommt aber ein paar Schritte weiter unten.) 8 Hier verwende ich die in das JavaScript-Array eingebaute Methode unshift, um ein Objekt am Anfang des Arrays hist einzufügen. Das Objekt, das ich hinzufüge, hat zwei Eigenschaften (url und title), die die beiden Informationen wiedergeben, die wir für die Beschriftung und die Funktion des Zurück-Buttons brauchen. 9 In dieser Zeile verwende ich die in das JavaScript-Array eingebaute Methode length, um herauszufinden, wie viele Objekte sich im hist-Array befinden. Wenn es dort nur ein Objekt gibt, bedeutet das, dass sich der Anwender auf der ersten Seite befindet und wir deshalb keinen Zurück-Button anzeigen müssen. Wenn es allerdings mehr Objekte im hist-Array gibt, müssen wir den Button in der Titelleiste einblenden. j Als Nächstes füge ich das .leftButton-Objekt ein, das ich zuvor erwähnt habe. Die Beschriftung der Schaltfläche soll der Titel der vorherigen Seite sein, den ich mit hist[1].title auslese. JavaScript-Arrays sind nullbasiert, so dass das erste Element (die aktuelle Seite) als Index die 0 trägt. Mit anderen Worten ist Index 0 die aktuelle Seite, Index 1 die vorherige Seite, Index 2 die Seite vor der vorherigen Seite und so weiter. k In diesem Codeblock binde ich eine anonyme Funktion an den Click-Handler des Zurück-Buttons. Denken Sie daran, dass dieser Code ausgeführt wird, wenn der Anwender klickt, und nicht, wenn die Seite lädt. Nachdem also die Seite geladen wurde und der Anwender auf den Zurück-Button geklickt hat, wird dieser Code ausgeführt. l Diese und die nächste Zeile verwenden die Array-Methode shift, um die ersten beiden Elemente des hist-Arrays zu entfernen. Die letzte Zeile der Funktion gibt dann die URL der vorherigen Seite an die Funktion loadPage() weiter. m Die restlichen Zeilen stammen unverändert aus früheren Beispielen. Deshalb werde ich sie hier nicht wiederholen. n Dies ist der Code für die URL-Prüfung, den wir schon weiter oben in diesem Kapitel verwendet haben. Bitte denken Sie daran, jonathanstark.com durch Ihren Domainoder Hostnamen zu ersetzen, da sonst keine Ihrer lokalen Links entführt und in die Seite geladen werden.
Ihr eigener Zurück-Button | 45
Bitte besuchen Sie http://de.selfhtml.org/javascript/objekte/array.htm für eine komplette Liste mit Beschreibungen und Beispielen der Array-Funktionen in JavaScript.
Nun, da wir unseren Zurück-Button haben, bleibt nur noch, ihn mit CSS aufzupeppen (siehe Beispiel 3-11). Ich beginne, indem ich den Text mit font-weight, text-align, lineheight, color und text-shadow verschönere. Dann platziere ich das div-Element genau dort, wo ich es haben möchte, indem ich position, top und left verwende. Anschließend stelle ich sicher, dass zu lange Texte mit Auslassungspunkten abgekürzt werden (maxwidth, white-space, overflow und text-overflow). Zum Schluss füge ich eine Grafik mit border-width und -webkit-border-image hinzu. Anders als das frühere Beispiel hat diese Grafik unterschiedliche Randbreiten links und rechts, da das Bild einen Pfeil nach links darstellt und dadurch asymmetrisch ist. Vergessen Sie nicht, dass Sie eine Grafik für diese Schaltfläche brauchen. Sie müssen sie unter dem Namen back_button.png im Ordner images abspeichern, der im Ordner Ihrer HTML-Datei liegt. Schlagen Sie für Tipps zum Bezug oder der Erstellung der Button-Bilder im Kapitel »Elementares Verhalten mit jQuery hinzufügen« auf Seite 25 nach. Beispiel 3-11: Fügen Sie diese Zeilen der Datei iphone.css hinzu, um die Zurück-Schaltfläche mit einer Randgrafik zu verschönern #header div.leftButton { font-weight: bold; text-align: center; line-height: 28px; color: white; text-shadow: rgba(0,0,0,0.6) 0px -1px 0px; position: absolute; top: 7px; left: 6px; max-width: 50px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-width: 0 8px 0 14px; -webkit-border-image: url(images/back_button.png) 0 8 0 14; }
Standardmäßig zeigt der mobile Safari einen durchscheinenden Kasten über klickbaren Objekten an, die gerade angetippt wurden (Abbildung 3-7). Da unser Button nicht rechteckig ist, sieht dieser Effekt wenig vorteilhaft aus, aber es ist ganz einfach, ihn abzustellen, was die App gleich viel schöner macht. Der mobile Safari unterstützt eine Eigenschaft namens -webkit-tap-highlight-color, die es Ihnen erlaubt, die Standardfarbe in jede beliebige Farbe zu ändern. Ich möchte die Hervorhebung komplett entfer-
46 | Kapitel 3: Fortgeschrittenes iPhone-Styling
nen, was ich durch das Setzen des Alphawerts auf komplette Transparenz erreicht habe (Beispiel 3-12).
Abbildung 3-7: Standardmäßig zeigt der mobile Safari einen durchscheinenden Kasten über klickbaren Objekten an, die gerade angetippt wurden. Beispiel 3-12: Fügen Sie die fett gedruckte Zeile der Datei iphone.css hinzu, um die StandardAntipphervorhebung des mobilen Safari zu löschen. #header div.leftButton { font-weight: bold; text-align: center; line-height: 28px; color: white; text-shadow: rgba(0,0,0,0.6) 0px -1px 0px; position: absolute; top: 7px; left: 6px; max-width: 50px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-width: 0 8px 0 14px; -webkit-border-image: url(images/back_button.png) 0 8 0 14; -webkit-tap-highlight-color: rgba(0,0,0,0); }
Im Fall des Zurück-Buttons kann es eine oder zwei Sekunden dauern, bis der Inhalt der vorherigen Seite erscheint. Um Frustrationen vorzubeugen, möchte ich, dass der Button sofort nach dem Drücken angeklickt aussieht. Bei einem Desktop-Browser wäre das eine einfache Sache, denn Sie würden nur Ihrer CSS-Datei eine Definition der :active-Pseudoklasse hinzufügen, um ein alternatives Layout für den Fall anzugeben, dass auf das
Ihr eigener Zurück-Button | 47
Objekt geklickt wurde. Ich weiß nicht, ob es ein Fehler oder eine Sonderfunktion ist, aber diese Vorgehensweise funktioniert nicht beim iPhone, denn der :active-Stil wird ignoriert. Ich habe ein wenig mit :active und :hover herumgespielt, was für Nicht-Ajax-Apps teilweise erfolgreich war, allerdings ist der :hover-Status bei Ajax-Apps wie dieser hier eingeklemmt (der Button bleibt zum Beispiel scheinbar gedrückt, wenn der Finger schon wieder weggenommen wurde). Zum Glück gibt es eine einfache Lösung. Ich verwende jQuery, um die Klasse clicked dem Button hinzuzufügen, sobald der Anwender darauf klickt. Ich habe mich dazu entschieden, eine dunklere Version der Schaltfläche im Beispiel einzufügen (siehe Abbildung 3-8 und Beispiel 3-13). Sie müssen sicherstellen, dass Sie eine Grafik namens back_ button_clicked.png im images-Unterordner haben. Schlagen Sie für Tipps zum Bezug oder der Erstellung der Button-Bilder im Kapitel »Elementares Verhalten mit jQuery hinzufügen« auf Seite 25 nach.
Abbildung 3-8: Es ist nur ein leichter Unterschied, aber der angeklickte Zurück-Button ist ein wenig dunkler als der im Standardzustand. Beispiel 3-13: Fügen Sie die folgenden Zeilen in die Datei iphone.css ein, damit der Zurück-Button angeklickt aussieht, sobald der Anwender darauf tippt #header div.leftButton.clicked { -webkit-border-image: url(images/back_button_clicked.png) 0 8 0 14; }
Da ich ein Bild für den gedrückten Zustand verwende, wäre es geschickt, dieses Bild vorzuladen. Andernfalls würde die Grafik des ungedrückten Zustands verschwinden, wenn der Zurück-Button erstmals gedrückt wird, solange die Grafik nachlädt. Ich werde das Vorladen von Bildern im nächsten Kapitel behandeln.
48 | Kapitel 3: Fortgeschrittenes iPhone-Styling
Da die CSS-Datei nun startklar ist, kann ich den Teil der Datei iphone.js anpassen, der für das Zuweisen des Click-Handlers an den Zurück-Button zuständig ist. Zuerst füge ich die Variable e der anonymen Funktion hinzu, um das hereinkommende click-Ereignis aufzufangen. Dann umhülle ich e.target mit einem jQuery-Selektor und rufe die jQueryFunktion addClass() auf, um meine CSS-Klasse clicked der Schaltfläche zuzuweisen: $('#header .leftButton').click(function(e){ $(e.target).addClass('clicked'); var thisPage = hist.shift(); var previousPage = hist.shift(); loadPage(previousPage.url); });
Ein besonderer Hinweis an alle CSS-Gurus unter Ihnen: Die CSS-SpriteTechnik ist hier keine Option, da sie die Definition von Offsets für die Bilder benötigt. Bild-Offsets werden von der Eigenschaft -webkit-borderimage aber nicht unterstützt.
Ein Icon für den Home-Bildschirm hinzufügen Hoffentlich gefällt den Anwendern Ihre Web-App so gut, dass sie auf ihrem Home-Bildschirm ein Icon (auch »Webclip-Icon« genannt) für Ihre App ablegen. Das machen sie, indem sie auf das Pluszeichen unten im Safari-Fenster drücken (Abbildung 3-9), dann auf ZUM HOME-BILDSCHIRM drücken (Abbildung 3-10) und dann oben rechts auf HINZUFÜGEN klicken (Abbildung 3-11). Standardmäßig wird das iPhone ein Icon aus einem Vorschaubild der Seite (inklusive Position und Zoomfaktor) erstellen, dem es runde Ecken und einen Glanzeffekt hinzufügt (Abbildung 3-12).
Abbildung 3-9: Hinzufügen eines Webclip-Icons zum Home-Bildschirm. Schritt 1: Drücken Sie auf den Plus-Button unten im Safari-Fenster.
Ein Icon für den Home-Bildschirm hinzufügen | 49
Abbildung 3-10: Schritt 2: Klicken Sie im Dialog auf »Zum Home-Bildschirm«.
Abbildung 3-11: Schritt 3: Klicken Sie oben rechts auf »Hinzufügen«.
Abbildung 3-12: Schritt 4: Ein 57 x 57 Pixel großes Bild erscheint im Home-Bildschirm.
Um das Icon für den Home-Bildschirm anzupassen, liefern coole Programmierer ein benutzerdefiniertes Webclip-Icon mit. Dafür ist es am einfachsten, ein einziges Icon für die gesamte Website zu definieren, indem man eine Datei namens apple-touch-icon.png in das Stammverzeichnis des Webservers legt. Die Datei sollte 57 x 57 Pixel groß sein und sowohl ohne abgerundete Ecken als auch ohne Glanzeffekt angelegt sein, da das iPhone
50 | Kapitel 3: Fortgeschrittenes iPhone-Styling
diese Effekte automatisch hinzufügt. Wenn Sie das iPhone daran hindern möchten, die Effekte anzuwenden, ändern Sie den Dateinamen einfach in apple-touch-icon-precomposed.png. In manchen Fällen werden Sie ein Webclip-Icon für eine Seite haben möchten, das sich von dem der gesamten Website unterscheidet. Sie können das erreichen, indem Sie eine der beiden folgenden Zeilen in den head-Bereich der »Verkehrspolizist«-HTML-Datei iphone.html ablegen (und gegebenenfalls MYCUSTOMICON.PNG durch einen absoluten oder relativen Pfad zum Bild ersetzen):
Möchten Sie vorgerenderte Bilder nutzen, verwenden Sie einen Eckradius von 10px oder mehr, da das iPhone die Ecken sonst mit einem Radius von 10px abschneiden wird. Auf jeden Fall wird bei vorgerenderten Bildern aber der Glanzeffekt weggelassen.
Vollbildmodus Sie möchten gern ein Viertel des vertikalen Platzes (104px, um genau zu sein) vom mobilen Safari zurückgewinnen? Dann fügen Sie einfach die folgende Zeile in den head-Bereich der »Verkehrspolizist«-HTML-Datei iphone.html ein, und Ihre Web-App wird sich im Vollbildmodus öffnen, nachdem Sie vom Webclip-Icon aus gestartet wurde. <meta name="apple-mobile-web-app-capable" content="yes" />
Ich hätte Ihnen schon früher von dieser Funktion erzählt, aber sie ist erst sinnvoll, wenn alle Links mit Ajax entführt wurden. Sobald der Anwender auf einen nicht entführten Link klickt – einen, der auf eine fremde Seite verweist –, wird sich der mobile SafariBrowser starten und die Seite ganz normal laden. Dieses Verhalten ist perfekt für das Beispiel, an dem wir gearbeitet haben, denn externe Links (Amazon, Twitter, Facebook usw.) werden sich in Safari öffnen.
Die Statusleiste verändern Haben Sie einmal das Metatag apple-mobile-web-app-capable hinzugefügt, haben Sie die Möglichkeit, die Farbe der 20px hohen Statusleiste ganz oben am Bildschirm mit dem Metatag apple-mobile-web-app-status-bar-style zu verändern. Die normale, graue Safari-Statuszeile ist der Standard (default), allerdings kann man sie auch auf Schwarz (black) setzen (siehe Abbildung 3-13). Wenn Sie als Wert black-translucent verwenden, wird sie halb transparent und außerdem vom Dokumentenfluss abgekoppelt. Das heißt, dass die Web-App beim ersten Laden um 20px nach oben (also hinter die Statusleiste) geschoben wird. Deshalb werden Sie gegebenenfalls die Position Ihrer Titelleiste anpassen müssen, um das zu kompensieren. <meta name="apple-mobile-web-app-status-bar-style" content="black" />
Vollbildmodus | 51
Veränderungen an der Farbe der Statusleiste werden erst wirksam, wenn die Web-App im Vollbildmodus gestartet wurde.
Abbildung 3-13: Der Vollbildmodus bringt etwa 25% mehr Platz und erlaubt es Ihnen, die Farbe der Statusleiste zu verändern.
Eine eigene Startgrafik hinzufügen Wenn eine Web-App im Vollbildmodus startet, wird dem Anwender ein Bildschirmfoto der App präsentiert, während die erste Seite lädt. Ich bin kein Freund dieser Lösung, denn es sieht so aus, als könne man die App bereits bedienen. Klickt man allerdings irgendwo, passiert nichts. Außerdem ist es ein Screenshot von der Stelle, an der der Anwender die Web-App zuletzt verlassen hat (inklusive Scrollposition) – nicht sehr attraktiv. Glücklicherweise erlaubt uns der mobile Safari, eine eigene Startgrafik zu definieren, die während des Ladens der Web-App angezeigt wird. Wenn Sie eine solche Startgrafik hinzufügen möchten, erstellen Sie eine 320 x 460 Pixel große PNG-Datei und speichern diese in denselben Ordner, in dem auch die HTML-Datei liegt. Als Nächstes fügen Sie die folgende Zeile in den head-Bereich der Datei iphone.html ein (ersetzen Sie dabei myCustomStartupGraphic.png durch einen absoluten oder relativen Pfad zu Ihrer Grafik):
Beim nächsten Start der App über das Webclip-Icon wird zuerst noch das alte Verhalten ausgelöst, bis die neue Startgrafik geladen wurde. Bei späteren Starts wird direkt Ihre Startgrafik gezeigt (Abbildung 3-14).
52 | Kapitel 3: Fortgeschrittenes iPhone-Styling
Abbildung 3-14: Eine App, die im Vollbildmodus startet, kann über eine eigene Startgrafik verfügen.
Was Sie gelernt haben In diesem Kapitel haben Sie gelernt, wie Sie eine normale Website in eine Vollbild-AjaxApp umwandeln, komplett mit Fortschrittsindikator, einem nativ aussehenden ZurückButton und einem eigenen Webclip-Icon. Im nächsten Kapitel werden Sie erfahren, wie Sie Ihre App zum Leben erwecken, indem Sie native Benutzeroberflächenanimationen hinzufügen. Ja – jetzt kommen die Themen, die richtig Spaß machen!
Was Sie gelernt haben | 53
Kapitel 4
KAPITEL 4
Animation
iPhone-Apps haben eine Menge markanter Animationscharakteristiken, die für den Anwender eine Bedeutung haben und ihn Zusammenhänge erschließen lassen. Es schieben sich zum Beispiel Seiten nach links, wenn Sie per Link auf Detailseiten gehen, und wieder nach rechts, wenn Sie zurückgehen. In diesem Kapitel werden Sie lernen, wie Sie Ihrer App charakteristische Verhaltensweisen, wie das Schieben, den Seiten-umblätternEffekt und mehr, beibringen. Durch diese Änderungen, in Kombination mit Ajax und dem Vollbildmodus, ist Ihre Web-App dann von einer nativen App fast nicht mehr zu unterscheiden.
Mit ein wenig Hilfe von unserem Freund Ich bin ganz ehrlich: Eine Webseite so zu animieren wie eine native iPhone-App, ist mühsam. Glücklicherweise hat ein unternehmungslustiger Typ aus Philadelphia namens David Kaneda eine JavaScript-Bibliothek namens jQTouch geschrieben, die die mobile Webentwicklung ein ganzes Stück einfacher macht. jQTouch ist ein Open SourcejQuery-Plug-in, das alles behandelt, was wir im letzten Kapitel gelernt haben, und zusätzlich eine ganze Bootsladung von komplexem Zeug, das man nur mit großem Aufwand von null an selbst programmieren könnte. Sie können die aktuelle Version von jQTouch unter http://jqtouch.com/ herunterladen.
Zur Hauptseite gleiten Wir werden eine einfache App zum Zählen von Kalorien entwickeln, die Kilo heißen soll und dem Anwender ermöglicht, Essenseinträge für ein bestimmtes Datum hinzuzufügen und zu löschen. Alles in allem wird es sechs Bedienfelder geben: HAUPTSEITE, EINSTEL-
| 55
LUNGEN, DATEN, DATUM, NEUER EINTRAG und ÜBER KILO. Wir werden mit zwei Bedienfeldern starten und uns dann weiter vorarbeiten.
Ich werde einigen HTML-Elementen (toolbar, edgetoedge, arrow, button, back usw.) CSS-Klassen zuordnen. Diese Klassen beziehen sich immer auf vordefinierte CSS-Klassen-Selektoren aus dem Standard-jQTouch-Layout. Behalten Sie bitte im Hinterkopf, dass Sie Ihre eigenen Klassen verwenden können, indem Sie das existierende jQTouch-Layout anpassen oder Ihr eigenes ganz neu erstellen; ich nutze hier die Standardversion.
Legen wir los, indem wir eine Datei namens index.html erstellen und den HTML-Code für die Hauptseite und das ÜBER KILO-Bedienfeld aus Beispiel 4-1 einfügen.
Abbildung 4-1: Kilo vor der Einbindung von jQTouch … Beispiel 4-1: Der HTML-Code für die Hauptseite und das Über Kilo-Bedienfeld Kilo
Beispiel 4-1: Der HTML-Code für die Hauptseite und das Über Kilo-Bedienfeld (Fortsetzung)
Mit Kilo können Sie über Ihr Essen Tagebuch führen.
Dieser HTML-Code besteht hauptsächlich aus einem head-Bereich mit einem Titel und einem body-Bereich mit zwei Kindern, beides div-Elemente: 1 Dieses div-Element wird (genauso wie das div-Element about, das ein paar Zeilen tiefer definiert wird) ein Bedienfeld der Applikation, da es ein direkter Abkömmling des body-Elements ist. 2 In jedem dieser Bedienfeld-div-Elemente gibt es ein div-Element mit der Klasse toolbar. Diese toolbar-Klasse ist im jQTouch-Layout speziell vordefiniert, um ein Element zu einer klassischen iPhone-Titelleiste umzustylen. 3 Diese ungeordnete Liste hat die Klasse edgetoedge, die jQTouch anweist, die Liste im sichtbaren Bereich von ganz links bis ganz nach rechts auszudehnen. 4 In dieser Zeile gibt es ein Listenelement, das einen Link beinhaltet, dessen href auf das ÜBER KILO-Bedienfeld zeigt. Das Einfügen der arrow-Klasse in das li-Element ist optional; damit wird ein Pfeil nach rechts am rechten Rand des Elements eingefügt. 5 Jedes toolbar-Element beinhaltet ein einzelnes h1-Element, das den Titel des Bedienfelds angibt. In dieser Zeile gibt es einen Link mit den Klassen button und back, die jQTouch befehlen, die Schaltfläche wie einen Zurück-Button aussehen zu lassen. Beachten Sie, dass die Eigenschaft href des Buttons auf # gesetzt ist. Normalerweise würde das dem Browser sagen, dass er zum Anfang der Seite zurückkehren soll. Wenn man allerdings jQTouch verwendet, navigiert es stattdessen zum vorherigen Bedienfeld zurück. In fortgeschritteneren Szenarien werden Sie eventuell lieber einen Anker verwenden (zum Beispiel #home), der dem Zurück-Button sagt, dass er zu einem bestimmten Bedienfeld springen soll, ohne auf die vorherige Seite zu achten.
Da die einfache HTML-Datei fertig ist, wird es nun Zeit, jQTouch zur Party einzuladen. Wenn Sie jQTouch einmal heruntergeladen und im Verzeichnis der HTML-Datei ausgepackt haben, müssen Sie lediglich ein paar Zeilen Code in den head-Bereich Ihrer Seite einfügen (Beispiel 4-2). Für dieses und andere Beispiele in diesem Buch müssen Sie jQTouch von der Seite http://jqtouch.com herunterladen, auspacken und die Verzeichnisse jqtouch und themes in denselben Ordner verschieben, in dem auch die HTML-Datei liegt. Außerdem müssen Sie im Ordner jqtouch die JavaScript-Datei (zum Beispiel jquery.1.3.2.min.js) in jquery.js umbenennen.
Zur Hauptseite gleiten | 57
Beispiel 4-2: Das Hinzufügen dieser Zeilen in den head-Bereich Ihres HTML-Dokuments aktiviert jQTouch 1 2 <script type="text/javascript" src="jqtouch/jquery.js">3 <script type="text/javascript" src="jqtouch/jqtouch.js">4 <script type="text/javascript">5 var jQT = $.jQTouch({ icon: 'kilo.png', statusBar: 'black' });
1 Ich binde die Datei jqtouch.css ein. Diese Datei definiert einige grundlegende strukturelle Designregeln, die sehr spezifisch für die Behandlung von Animationen, Ausrichtung und andere iPhone-typische Details sind. Diese Datei wird zwingend benötigt, und es sollte keinen Grund für Sie geben, sie zu verändern. 2 Ich binde die CSS-Datei für mein ausgewähltes Layout ein, in diesem Fall das »jqt«Layout, das mit jQTouch ausgeliefert wird. Die Klassen, die ich in meiner HTMLDatei verwendet habe, passen zu den Selektoren in diesem CSS-Dokument. jQTouch wird standardmäßig mit zwei Layouts ausgeliefert. Sie können aber auch Ihr eigenes Design erstellen, indem Sie entweder ein vorhandenes Layout duplizieren und verändern oder es ganz neu aufsetzen. 3 Da jQTouch jQuery benötigt, binde ich das hier ein. jQTouch bringt bereits eine Kopie von jQuery mit, aber Sie können auch auf eine andere Version verweisen, wenn Sie möchten. 4 Hier binde ich jQTouch selbst ein. Bitte beachten Sie, dass Sie jQTouch nach jQuery einbinden, da sonst nichts funktionieren wird. 5 So kommen wir zum script-Block, in dem ich das jQTouch-Objekt initialisiere und zwei Eigenschaften Werte zuweise: icon und statusBar. jQTouch bietet einige Eigenschaften an, mit denen man das Verhalten und das Erscheinungsbild der App steuern kann. Sie werden in diesem Buch einige Beispiele dafür finden, sie sind alle optional. Allerdings werden Sie fast immer wenigstens ein paar von ihnen anwenden. In diesem Fall sagt icon jQTouch, wo das Webclip-Icon zu finden ist, und statusBar stellt die Farbe der 20px-Statuszeile am oberen Bildrand für den Vollbildmodus ein. Übrigens geht jQTouch davon aus, dass man den Vollbildmodus verwenden möchte, denn … na eben. Sollten Sie wider Erwarten doch einmal keinen Vollbildmodus wünschen, fügen Sie der Eigenschaftenliste einfach fullScreen: false hinzu.
Der Unterschied zwischen der App vor jQTouch (Abbildung 4-1) und danach (Abbildung 4-2) ist dramatisch, aber das wirklich Erstaunliche ist, dass Sie mit zehn Zeilen
58 | Kapitel 4: Animation
Code den großartigen links/rechts-Schiebeeffekt eingebaut haben. Außerdem haben Sie den Vollbildmodus aktiviert, die Farbe der Statusleiste gesetzt und Ihr eigenes WebclipIcon hinzugefügt. jQTouch ist echt krass, und wir haben gerade einmal angefangen.
Abbildung 4-2: … und Kilo nach jQTouch.
Das Daten-Bedienfeld hinzufügen Lassen Sie uns nun das DATEN-Bedienfeld hinzufügen. Es wird eine Liste relativer Daten beinhalten, die aktuell beginnen und fünf Tage zurückreichen (Abbildung 4-3). Fügen Sie den HTML-Code für das DATEN-Bedienfeld (wie in Beispiel 4-3 gezeigt) direkt nach dem ÜBER KILO-Bedienfeld und noch vor dem schließenden
ein. Beispiel 4-3: Der HTML-Code für das Daten-Bedienfeld
Wie das ÜBER KILO-Bedienfeld hat auch das DATEN-Bedienfeld eine Titelleiste mit Titel und Zurück-Button. Nach der Titelleiste gibt es eine ungeordnete edgetoedge-Liste mit Links. Beachten Sie, dass alle Links eindeutige IDs (0 bis 5), aber dasselbe href-Ziel (#date) haben – dazu später mehr.
Das Daten-Bedienfeld hinzufügen | 59
Abbildung 4-3: Das Daten-Bedienfeld verfügt über eine Titelleiste mit einem Zurück-Button und eine Liste anklickbarer Daten.
Als Nächstes müssen Sie die Hauptseite mit einem Link auf das DATEN-Bedienfeld versehen. Fügen Sie die im Folgenden fett gedruckte Zeile dem div-Element mit der ID home in der Datei index.html hinzu:
Abbildung 4-4: Die Hauptseite besitzt nun einen Link zum Daten-Bedienfeld.
60 | Kapitel 4: Animation
Und schon haben wir der App ein neues Bedienfeld hinzugefügt (siehe Abbildung 4-4). Wenn man auf ein Element im DATEN-Bedienfeld klickt, passiert allerdings noch nichts. Lassen Sie uns das beheben, indem wir das DATUM-Bedienfeld einfügen.
Das Datum-Bedienfeld hinzufügen Das DATUM-Bedienfeld sieht den anderen Bedienfeldern sehr ähnlich, hat aber einige Erweiterungen (siehe Beispiel 4-4). Fügen Sie den HTML-Code für das DATUM-Bedienfeld direkt nach dem DATEN-Bedienfeld, aber noch vor dem schließenden ein. Beispiel 4-4: Der HTML-Code für das Datum-Bedienfeld
1 Die Titelleiste des DATUM-Bedienfelds hat einen weiteren Button. Wenn er angeklickt wird, soll das NEUER EINTRAG-Bedienfeld (das wir noch nicht eingebaut haben) angezeigt werden. Ich habe dem Link die Klasse slideup gegeben, die jQTouch sagt, dass das Zielbedienfeld von unten nach oben auf den Bildschirm geschoben werden soll (anders als beim normalen Navigationsverhalten horizontal von rechts nach links). 2 Der nächste untypische Aspekt dieses Bedienfelds ist, dass ich ein Listenelement definiert habe, für das ich die Eigenschaft style auf display:none gesetzt habe, wodurch es unsichtbar wird. Wie Sie gleich sehen können, werde ich diesen Listeneintrag als Vorlage für neue Einträge verwenden, sobald sie erstellt worden sind. Zu diesem Zeitpunkt gibt es noch keine Einträge, und das Bedienfeld wird bis auf die Titelleiste leer sein. Da Sie nun das DATUM-Bedienfeld eingefügt haben, wird nach einem Klick auf einen Eintrag im DATEN-Bedienfeld das leere DATUM-Bedienfeld (Abbildung 4-5) hineingeschoben.
Das Datum-Bedienfeld hinzufügen | 61
Abbildung 4-5: Bis auf die Titelleiste ist das Datum-Bedienfeld anfangs leer.
Das Neuer Eintrag-Bedienfeld hinzufügen Beispiel 4-5 zeigt den Quelltext für das NEUER EINTRAG-Bedienfeld. Fügen Sie ihn in die Datei index.html direkt vor ein. Beispiel 4-5: Der HTML-Code für das Neuer Eintrag-Bedienfeld
1 Das Erste, das man beim NEUER EINTRAG-Bedienfeld hervorheben muss, ist, dass es keinen Zurück-Button mehr hat, sondern stattdessen eine Abbrechen-Schaltfläche. Abbrechen-Buttons verhalten sich in jQTouch genauso wie Zurück-Buttons, indem sie die aktuelle Seite in umgekehrter Weise aus dem Bild heraus animieren, in der sie hineinanimiert wurde. Allerdings sieht der Abbrechen-Button im Gegensatz zum Zurück-Button nicht wie ein Pfeil nach links aus.
62 | Kapitel 4: Animation
Ich habe hier einen Abbrechen-Button verwendet, da sich das NEUER EINTRAG-Bedienfeld von unten ins Bild schiebt und deshalb auch wieder nach unten verschwindet. Es wäre verwirrend, wenn der Button nach links zeigt, beim Drücken das Bedienfeld aber nach unten animiert wird.
2 Dieses HTML-Formular beinhaltet eine ungeordnete Liste mit drei Einträgen: zwei Textfeldern und einer Absenden-Schaltfläche. Das Einbetten eines Formulars in Listenelemente erlaubt es dem jQTouch-Layout, das Formular wie in Abbildung 4-6 zu stylen. Jedes Texteingabefeld besitzt ein paar definierte Attribute: type
Definiert das Formularelement als einzeiliges Eingabefeld. placeholder
Ein Text, der im Eingabefeld angezeigt werden soll, solange es noch leer ist. name
Der Name, dem der vom Anwender eingegebene Wert zugeordnet wird, sobald das Formular abgeschickt wurde. id
Eine im Kontext der gesamten Seite eindeutige ID für das Element. autocapitalize
Eine spezielle Einstellung für den mobilen Safari-Browser, die es Ihnen erlaubt, die voreingestellte automatische Großschreibefunktion zu deaktivieren. autocorrect
Eine spezielle Einstellung für den mobilen Safari, die es Ihnen erlaubt, die voreingestellte automatische Rechtschreibkorrektur zu deaktivieren. autocomplete
Diese Einstellung erlaubt das Abschalten der automatischen Vervollständigungsfunktion des mobilen Safari. 3 Das class-Attribut der EINTRAG SPEICHERN-Schaltfläche erfordert ein paar erklärende Worte. Das iPhone zeigt die Tastatur an, sobald sich der Cursor in einem Eingabefeld befindet. Diese Tastatur hat unten rechts eine GO-Taste, die das Formular absendet, sobald sie gedrückt wurde. Wenn Sie die Absendefunktion entführen, wie wir es hier tun, wird der Cursor nicht aus dem Eingabefeld entfernt, und die Tastatur bleibt im Bild. Um das zu beheben, bietet jQTouch eine bequeme Methode, die automatisch den Cursor aus dem aktiven Eingabefeld nimmt, sobald ein Formular abgesendet wurde. Um von dieser Funktionalität zu profitieren, müssen Sie dem Absende-Button des Formulars lediglich die submit-Klasse hinzufügen. Abbildung 4-7 zeigt das NEUER EINTRAG-Bedienfeld in Aktion. Bis jetzt habe ich noch nichts unternommen, damit der Eintrag wirklich abgespeichert wird, wenn der Anwender auf EINTRAG SPEICHERN klickt. Das werden wir aber in Kapitel 5 behandeln.
Das Neuer Eintrag-Bedienfeld hinzufügen
| 63
Abbildung 4-6: Das jqt-Layout leistet beim Formatieren von Formularen gute Dienste.
Abbildung 4-7: Tastatureingabe beim Neuer Eintrag-Formular.
Das Einstellungen-Bedienfeld Wir haben bislang noch keinen Button definiert, der den Anwender in das EINSTELLUNGEN-Bedienfeld navigieren lässt, also fügen wir einen in die Titelleiste der Hauptseite ein (Abbildung 4-8). Alles was wir dazu brauchen, ist die fett gedruckte Zeile in folgendem Code:
1 In dieser Zeile wird der Button eingefügt. Beachten Sie, dass ich dem Link die Klasse flip zugewiesen habe. Sie weist jQTouch an, dass die Animation von der Hauptseite zum EINSTELLUNGEN-Bedienfeld eine Rotation um die vertikale Achse sein soll. Um das noch ein wenig echter aussehen zu lassen, wird die Seite während der Animation ein wenig nach hinten verschoben, genau so wie es die auf dem iPhone vorinstallierte Wetter-App macht. Schick, oder?
Abbildung 4-8: Der Einstellungen-Button wurde der Titelleiste auf der Hauptseite hinzugefügt.
Im Vergleich mit dem NEUER EINTRAG-Bedienfeld sieht der HTML-Code des EINSTELLUNGEN-Bedienfelds sehr vertraut aus (Beispiel 4-6). Es gibt ein weiteres Texteingabefeld,
und einige Attribute sind weggefallen oder haben andere Werte, aber im Prinzip sind sie gleich. Fügen Sie den Code auf die gleiche Weise wie bei den anderen Bedienfeldern in Ihre HTML-Datei ein. Wenn Sie fertig sind, sollte das EINSTELLUNGEN-Bedienfeld wie in Abbildung 4-9 aussehen. Genauso wie das NEUER EINTRAG-Formular speichert auch das EINSTELLUNGEN-Formular noch keine Informationen ab. Das steht, wie bereits gesagt, im nächsten Kapitel auf dem Plan. Beispiel 4-6: Der HTML-Code für das Einstellungen-Bedienfeld
Beispiel 4-6: Der HTML-Code für das Einstellungen-Bedienfeld (Fortsetzung)
Abbildung 4-9: Das Einstellungen-Bedienfeld.
Alles zusammenfügen Damit haben wir es! Mit weniger als 100 Zeilen Code haben wir eine iPhone-isierte Benutzeroberfläche für eine Applikation mit sechs Bedienfeldern inklusive Animationen für die Seitenübergänge erstellt. Beispiel 4-7 zeigt den gesamten fertigen HTML-Code. Beispiel 4-7: Der fertige HTML-Code für die App mit sechs Bedienfeldern
Beispiel 4-7: Der fertige HTML-Code für die App mit sechs Bedienfeldern (Fortsetzung) <script type="text/javascript"> var jQT = $.jQTouch({ icon: 'kilo.png', statusBar: 'black' });