Posthistorie
Über die in den beiden ersten Tutorialteilen vorgestellten Elemente hinaus können Entwickler Mozilla-Anwendungen beliebig erweitern - beispielsweise eine History-Funktion fürs Mail- oder News-Lesen. Das erfordert allerdings weitere Theoriebröckchen.
- Karsten DĂĽsterloh
Ging es in den ersten beiden Teilen dieses Tutorials darum, einen Ăśberblick ĂĽber die von XUL angebotenen Layout-Elemente zu bekommen, sollen die dabei erworbenen Kenntnisse jetzt endlich in ein produktives Miniprojekt umgesetzt werden: eine Erweiterung fĂĽr die Mozilla-Mail-Komponenten, fĂĽr Mail und News der Mozilla-Suite und dessen Standalone-Ableger Thunderbird.
Beiden fehlt eine Nachrichtenhistorie, in der Anwender ähnlich wie in einem modernen Browser in der Liste der schon gelesenen Nachrichten frei vor- und zurückspringen können. Die hier entwickelte Erweiterung Mistory (für „Message History“) erhebt keinen Anspruch auf Eleganz oder gar Effizienz, sie soll vielmehr einige der besprochenen Techniken in einen sinnvollen Zusammenhang bringen. Dennoch steht am Anfang dieses Artikels wieder etwas Theorie.
Moderne Benutzeroberflächen bieten in der Regel mehrere Wege zur Ausführung eines Kommandos an: Tastaturkürzel, Menüleisten, Knöpfe et cetera. Sollen alle diese Elemente stets denselben Status widerspiegeln (beispielsweise deaktiviert sein), bedarf es unter Umständen einer aufwendigen Synchronisationslogik. XUL sucht dies zu vereinfachen, indem es ein broadcaster-Element anbietet, das andere XUL-Elemente beobachten können. Alle Attributwerte (mit Ausnahme von id und persist) eines broadcaster reicht die XUL-Engine an die Beobachter durch, die somit stets auf demselben Stand sind. Änderungen der Attributwerte sind immer zentral am broadcaster vorzunehmen.
broadcast Elemente beobachten
Üblicherweise enthalten globale broadcastersets die in einem XUL-Dokument angelegten broadcaster, die über eigene ids referenzierbar sind. Ein XUL-Element, das einen bestimmten broadcaster beobachten möchte, braucht nur sein observes-Attribut auf die id des gewünschten broadcaster zu setzen. Möchte man nur bestimmte Attribute eines broadcaster beobachten, ohne deshalb gleich eine broadcaster-Hierarchie aufzubauen, kann man anstelle des observes-Attributs das observes-Element als Kind des Beobachters notieren.
<broadcasterset>
<broadcaster id="cmd_mycommand" collapsed="true"/>
</broadcasterset>
<button id="btn_mycommand" label="Kommando!" observes="cmd_mycommand"/>
<menuitem id="mi_mycommand" label="Kommando!" observes="cmd_mycommand"/>
Über das Attribut element muss in diesem Fall die id des broadcaster referenziert werden, das Attribut attribute erwartet den Namen des zu beobachtenden Attributs; jedes solche Attribut bedarf eines eigenen observes-Elements. Beobachter eines broadcaster können zudem in ihrem onbroadcast-Ereignisattribut auf Attributswertänderungen direkt reagieren.
<broadcaster id="bc_label" label="Kommando!" style="color: black"/>
<button>
<observes element="bc_label" attribute="label" onbroadcast="alert('Neuer Test!');"/>
</button>
Das style-Attribut wird nicht an den Button weitergegeben, nur das label. Bei einer Änderung desselben in bc_label wird ein broadcast-Ereignis versandt und dadurch das alert des button ausgelöst.
Kommandos in commandset-Elementen
Eine spezielle Variante des broadcaster ist das command-Element. Nutzt man broadcaster üblicherweise zur zentralen Verwaltung normaler Attribute, versammelt man Ereignis-Attribute wie oncommand meist in commandsets logisch zusammengehörender command-Elemente. Anstelle des oncommand-Attributs verweist in diesem Fall command="Command-ID" auf das gewünschte command.
<command id="cmd_mistoryback" disabled="true" oncommand="gkoMistory.onBack(event)"/>
<menuitem id="mistoryMenuBack" position="2" label="&mistoryGo.label;"
accesskey="&mistoryGo.accesskey;" key="key_mistoryback" observes="cmd_mistoryback"/>
Diese Konstruktion bietet den Vorteil, dass die fehleranfällige Duplizierung von Codebruchstücken entfällt, denn nun enthält nur das command-Element ein oncommand-Ereignis-Attribut mit dem auszuführenden Code. Das command-Element verhält sich im Übrigen wie ein normaler broadcaster und lässt sich wie üblich beobachten. In Mozilla-Anwendungen sind command-Elemente darüber hinaus in aller Regel an die nsIController-Schnittstelle des Backends „angeschlossen“, das eine zentrale, effiziente Behandlung des Aktivierungstatus bietet (siehe Listing 1).
Listing 1: nsIController.idl (Auszug)
Die Methoden eines Controllers versammeln die Behandlung von Kommandos an einem zentralen Ort.
interface nsIController : nsISupports
{
boolean isCommandEnabled(in string command);
boolean supportsCommand(in string command);
void doCommand(in string command);
void onEvent(in string eventName);
};
Dazu muss ein Javascript-Objekt, das die vier nsIController-Methoden mit Leben fĂĽllt, erstellt und beispielsweise ĂĽber top.controllers.appendController(this.mistoryCommandController); in die globale Ereignisbehandlung eingefĂĽgt werden. Die einzelnen oncommand-Attribute der command-Elemente rufen nur die zentrale Funktion goDoCommand(command) des globalen Mozilla-Pakets auf, die fĂĽr den Aufruf der konkreten Schnittstellenfunktionen sorgt.
SchlĂĽsselgewalt: key als Element und Attribut
Soll ein Kommando über einen einfachen Tastaturgriff zugänglich sein, bietet XUL das key-Element an. Über dessen key-Attribut kann man eine Taste bestimmen, deren Betätigung das Kommando, notiert im command- oder oncommand-Attribut auslöst. Für nicht druckbare Zeichen steht alternativ das Attribut keycode zur Verfügung, es nimmt symbolische Namen wie „VK_LEFT“ (Pfeiltaste links) oder „VK_ENTER“ (Eingabetaste des Zehnerblocks) entgegen.
Zusätzlich kann man mit dem modifiers-Attribut die Verwendung üblicher Steuertasten erzwingen, als Attributwert erwartet modifiers eine komma- oder leerzeichengetrennte Liste dieser Angaben: shift (die Umschalttaste), alt (die Alt- oder Auswahl-Taste), meta (die Meta- oder Befehlstaste; nicht auf PCs), control (die Steuerungstaste) und accel (die Tastaturkürzeltaste der jeweiligen Plattform, also control für Windows- oder meta auf Apple-Rechnern).
<key id="key_mistoryback" command="cmd_mistoryback" keycode="VK_LEFT" modifiers="alt"/>
Solcherart definierte Tasten sind von anderen XUL-Elementen unabhängig, lassen sich aber über ihre id von menuitems in deren key-Attribut referenzieren und zeigen dann die jeweilige Tastenkombination als Text an. Soll der vordefinierte Text überschrieben werden, muss man am key-Element ein diesbezügliches keytext-Attribut notieren. key-Elemente residieren üblicherweise gemeinsam in einem globalen keyset.
Einmalige Entities statt Texte
Unter den bisher vorgestellten XUL-Elementen waren schon einige, die Texte in natürlicher Sprache als Inhalt oder Attributwert entgegennehmen. Dies führt allerdings zum einen dazu, dass Änderungen an Texten stets eine Anpassung der dazugehörigen XUL-Datei implizieren, obwohl die eigentliche Verarbeitungslogik der Anwendung überhaupt nicht betroffen ist. Zum anderen erschwert ein solches Vorgehen den Abgleich mehrfach vorkommender Texte und deren Wiederverwendbarkeit.
Als Ausweg nutzt XUL die aus XML bekannten Dokumenttypdefinitionen (DTDs) und erlaubt die Definition eigener Entitäten, die Entwickler anstelle der Texte verwenden können. Da diese Entitäten zudem in andere Dateien ausgelagert sein können (siehe Listing 2b), sind die obigen Schwierigkeiten damit behoben.
Listing 2a: dtd.xul
Das Nachladen von DTDs erlaubt die Mozilla-Plattform nur von vertrauens-wĂĽrdigen Umgebungen; diese XUL-Datei braucht daher schon Chrome-Rechte, beispielsweise als Teil einer Erweiterung.
<?xml version="1.0"?>
<!DOCTYPE window SYSTEM "dtd.dtd" >
<window
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&dtd.title;">
<stringbundle id="dtd_props"
src="chrome://branding/locale/brand.properties"/>
<commandset>
<command id="dtd_cmd" oncommand="&dtd.command;"/>
</commandset>
<keyset>
<key id="dtd_key"
key="&dtd.key.key;"
modifiers="&dtd.key.modifiers;"
keytext="&dtd.key.keytext;"
command="dtd_cmd"/>
</keyset>
<menubar>
<menu label="&dtd.menu.label;"
accesskey="&dtd.menu.accesskey;">
<menupopup>
<menuitem label="&dtd.item.label;"
accesskey="&dtd.item.accesskey;"
key="dtd_key"
command="dtd_cmd"/>
</menupopup>
</menu>
</menubar>
</window>
Listing 2b: dtd.dtd
DTD-Dateien mĂĽssen im UTF-8-Format vorliegen und können zwar eigene, aber keine benannten HTML-Entitäten wie ü benutzen. Nicht-ASCII-Zeichen mĂĽssen daher als Unicode-Zahlwert-Entitäten notiert werden.
<!ENTITY dtd.title "Texte per DTD">
<!ENTITY dtd.command "alert(document
.getElementById('dtd_props')
.getString('brandShortName'))">
<!ENTITY dtd.key.key "x">
<!ENTITY dtd.key.modifiers "accel">
<!ENTITY dtd.key.keytext "X-Taste">
<!ENTITY dtd.menu.label "Menütitel">
<!ENTITY dtd.menu.accesskey "M">
<!ENTITY dtd.item.label "Menüeintrag">
<!ENTITY dtd.item.accesskey "e">
Bei der Verarbeitung von Texten auf Javascript-Ebene müsste man bei Nutzung des DTD-Mechanismus erst reichlich umständlich alle benötigten Texte in XUL-Element-Attribute laden und von dort auslesen. Aus diesem Grund steht das stringbundle-Element zur Verfügung, das in seinem src-Attribut eine zu ladende Datei im Java-Property-Format übergeben bekommen muss. Über die getString-Methode kann man auf die Texte des stringbundles zugreifen.
overlay: Einbinden von Strukturen
Wer oft genutzte XUL-Strukturen wiederverwerten will, dem bietet sich die Auslagerung in eine eigene Datei an. Diese versammelt alle ausgelagerten Strukturen unter dem XUL-Wurzel-Element overlay; alle direkten Kindelemente der Wurzel sollten eine id besitzen.
<overlay id="mistoryButtonsOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<hbox id="mistoryToolbarBox">
<!-- ... -->
</hbox>
</overlay>
Durch eine XML-Instruktion der Form ?xul-overlay href=“auslagerung.xul“? können alle interessierten XUL-Dokumente die Strukturen einbinden, üblicherweise noch vor deren Wurzelelement. Trifft der XUL-Parser beim Lesen des Dokuments auf ein solches Element mit id, ergänzt er es durch die Struktur aus der Auslagerungsdatei:
<?xml-stylesheet type="text/css" href="chrome://mistory/skin/mistory.css"?>
<?xul-overlay href="chrome://mistory/content/mistory-buttons.xul"?>
<!DOCTYPE overlay SYSTEM "chrome://mistory/locale/mistory.dtd">
<overlay id="mistoryMailWindowOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<!-- ... -->
</overlay>
Über einige Attribute lässt sich das Ergänzen noch feiner steuern: insertbefore und insertafter nehmen eine kommagetrennte Liste von Element-ids entgegen und positionieren das aktuelle Element vor oder hinter dem ersten davon gefundene Geschwisterelement derselben Ebene. Alternativ kann man mit position direkt eine numerische Position angeben. removeelement=“true“ entfernt das Element aus dem XUL-Dokument.
<hbox id="mistoryToolbarBox" insertafter="button-newmsg"/>
Der beschriebene Auslagerungsmechanismus erfordert schon bei der Erstellung der XUL-Anwendung, dass die genutzten Auslagerungsdateien bekannt sind; solche overlays heißen „statisch“. Allerdings erlaubt die Mozilla-Plattform über die Chrome-Registry außerdem „dynamische“ Überlagerungen von XUL-Elementen durch overlay - ohne Angabe von XML-Instruktionen. Dazu wird in der Beschreibungsdatei eines XUL-Pakets eine Liste der zu überlagernde Dateien und ihrer overlays angelegt (dazu später mehr). Der Überlagerungsalgorithmus ist jedoch derselbe.
XUL-Persistenz
XUL bietet einen einfachen Weg, Attributwerte zwischen verschiedenen Programmläufen zu speichern: Das Attribut persist nimmt eine leerzeichengetrennte Liste von Attributnamen entgegen, deren Werte über das Programmende hinaus gespeichert und beim nächsten Start wiederhergestellt werden sollen.
Dieser Mechanismus greift nur bei Programmstart und -ende, zwischenzeitlich kann man jedoch auch auf interner Javascript-Ebene ĂĽber die von window.document implementierte Schnittstelle nsIDOMXULDocument darauf zugreifen:
document.persist("Element-ID", "Attributname");
speichert den Wert des Attributs, sodass er beim nächsten Programmstart zur Verfügung steht. Die Werte ruhen zwischenzeitlich im Profil des Nutzers in der RDF-Datei localstore.rdf, unterschieden nach zugehöriger XUL-Datei und Element-ID.
Eine andere Möglichkeit der Wiederverwertung oft genutzter XUL-Strukturen bietet der Entwurf eigener Elemente. Zu diesem Zweck kennt die Mozilla-Plattform einen weiteren XML-Dialekt, die Extensible Bindings Language (XBL). Viele der bisher vorgestellten XUL-Elemente sind im Grunde bloß eigenschaftslose XML-Elemente, denen XBL ein bestimmtes Verhalten aufzwingt.
Neben eigenen XUL-Unterstrukturen lassen sich so einem Element bestimmte Verhaltensweisen zuweisen, beispielsweise wie das Element auf Tastendruck oder andere Ereignisse zu reagieren hat. AuĂźerdem kann man einem Element eigene Methoden und Properties beigeben.
Eine XBL-Datei kann mehrere solche Definitionen enthalten, so genannte Bindings. Diese lassen sich über ihre id mit speziellen CSS-Regeln der Form -moz-binding:url(chrome://mistory/content/merge.xbl#mistoryMerge) an die gewünschten Elemente binden. Die Wurzel einer XBL-Datei ist das bindings-Element. Als Kinder sollten nur binding-Elemente auftreten, die mindestens eine id besitzen, damit sie später referenzierbar sind. Des Weiteren können Bindings voneinander abgeleitet werden, indem man ihnen ein extends-Attribut der Form extends=“Dateiname#Binding_ID“ mitgibt. Sie erben den Inhalt des anderen binding, sofern sie ihn nicht durch eigene überschreiben.
<bindings id="mistoryBindings" xmlns="http://www.mozilla.org/xbl">
<binding id="mistoryMerge" extends="chrome://global/content/bindings/menu.xml#menu">
<implementation>
<constructor>
<![CDATA[
// merge all children's content
// (all children are <menupopup>s!)
]]>
</constructor>
</implementation>
</binding>
</bindings>
Jedes binding kennt wiederum vier Kindelemente: resources, content, handlers und implementation. Das resources-Element lädt andere Ressourcen wie Bilder oder CSS-Stylesheets in den binding-Kontext; dazu stehen die Unterelemente image und stylesheet zur Verfügung. Beide nehmen in ihrem src-Attribut die URI der Ressource entgegen und sind über ihre id zugänglich.
Im content-Element stehen die für normale DOM-Funktionen später unsichtbaren XUL-Elemente, der so genannte anonyme Inhalt (anonymous content). Auf ihn kann man auf Javascript-Ebene nur durch die Funktionen getAnonymousElementByAttribute und getAnonymousNodes des aktuellen XUL-Dokumentes zugreifen.
Verhalten modifizieren
Ăśber das Unterelement children lassen sich in den content die Kindelemente des Elements einfĂĽgen, dem dieses binding zugewiesen wurde. Diese Elemente erscheinen dann anstelle von children, allerdings kann dies ĂĽber sein includes-Attribut noch einen Elementfilter setzen - includes="treecols" erlaubt nur treecols als einzufĂĽgende Elemente.
<binding id="toolbarpaletteitem"
extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:button">
<content>
<xul:hbox class="toolbarpaletteitem-box" flex="1" xbl:inherits="type,place">
<children/>
</xul:hbox>
</content>
</binding>
Ereignisbehandlung definieren handler in XBL, gruppiert in einem handlers-Element. Jeder solche handler behandelt einen bestimmten Ereignistypen, der in seinem event-Attribut notiert sein muss. Über Attribute wie button, clickcount, charcode, keycode oder modifiers können Entwickler den handler auf bestimmte Klicks oder Tastenkombinationen spezialisieren (siehe Listing 3).
Listing 3: merge.xbl (Ausschnitt)
handler-Elemente bestimmen Ereignistypen wie hier mousedown und was im Falle ihres Eintretens zu geschehen hat.
<binding id="treebody"
extends="chrome://global/content/bindings/tree.xml#tree-base">
<implementation>
<constructor>
if ("_ensureColumnOrder" in this.parentNode)
this.parentNode._ensureColumnOrder();
</constructor>
<field name="_lastSelectedRow">
-1
</field>
</implementation>
<handlers>
<!-- If there is no modifier key, we select on mousedown, not
click, so that drags work correctly. -->
<handler event="mousedown" clickcount="1">
<![CDATA[
if (((!event.ctrlKey || !this.parentNode.pageUpOrDownMovesSelection) &&
!event.shiftKey && !event.metaKey) ||
this.parentNode.view.selection.single) {
<!-- ... -->
}
]]>
</handler>
Den eigentlichen Code zur Ereignisbehandlung enthält entweder das action-Attribut oder der Textinhalt des handler; wie in HTML oder XUL steht eine vordefinierte Variable event mit den Details des Ereignisses zur Verfügung. implementation schließlich dient als Container für eine Reihe weiterer Elemente: field, property, constructor, destructor and method.
Ein field definiert eine einfache Variable oder Konstante (fĂĽr readonly="true") auf dem gebundenen Element, deren Name das name-Attribut festlegt. Etwas flexibler ist das property-Element, da es darĂĽber hinaus ĂĽber spezielle Funktionen zum Lesen und Setzen des Wertes verfĂĽgt. Das onget-Attribut nimmt Code auf, der zum Tragen kommt, wenn XUL den property-Wert lesend benutzt; der Code sollte einen sinnvollen Wert zurĂĽckliefern. Komplexere Skripte sollte das Unterelement getter enthalten.
Das onset-Attribut nimmt den Code auf, der bei Zuweisungen an property aufzurufen ist. Die Variable var ist mit dem zu setzenden Wert vorbesetzt, der Code sollte einen Wert zurückliefern, um die Nutzung des property in komplexeren Ausdrücken zu ermöglichen. Längere Skripte sollten im Unterelement setter abgelegt sein. Der im action-Attribut oder als Textinhalt des Elementes constructor notierte Code wird beim ersten Anbinden eines binding aufgerufen, der in destructor bei dessen Vernichtung.
Eigene Methoden kann das method-Element spezifizieren. Dessen Attribut name bestimmt wieder den Namen der Funktion, das eventuell mehrfach vorkommende Unterelement parameter legt darĂĽber den Namen der Ăśbergabevariablen fest. Der Code einer method wird als Textinhalt des Unterelements body angegeben.
Mail: Erweiterung durch Mistory
Ein gutes Anschauungsbeispiel fĂĽr XBL-Bindings ist in Mozilla-basierten Browsern unter dem URL chrome://global/content/bindings/tree.xml zu finden. Diese Datei erzeugt das ĂĽbliche Aussehen und Verhalten eines XUL-trees und nutzt nahezu alle der verfĂĽgbaren XBL-Elemente. In Mistory dient XBL dazu, um eine fehlende Element-id herumzuprogrammieren.
Mistory ist eine Erweiterung für aktuelle Mozilla- und Thunderbird-Versionen, die dem Mailer eine Nachrichtenhistorie beschert. Dazu stellt die Erweiterung zwei Knöpfe für die Werkzeugleiste zur Verfügung (in Thunderbird manuell über Anpassen der Leiste einzufügen), die eine Vor-Zurück-Navigation in den bis dato betrachteten Nachrichten erlauben. Analog zum Browser besitzen beide Knöpfe eine ausklappbare Liste der verfügbaren Nachrichten, sodass Anwender gezielt auf bestimmte Nachrichten zurückgreifen können. Die Tiefe der jeweiligen Liste bestimmt die user_pref(„extensions.mistory.depth“, 20);.
Mit „Alt+Pfeil links“ und „Alt+Pfeil rechts“ stehen direkte Zugriffstasten bereit, die intern ebenso wie die Knöpfe auf das entsprechende command geleitet werden. Die Nachrichtenlisten sind als menuitem-template realisiert, die eine vollkommen im Speicher liegende RDF-Datenquelle versorgen. Zudem sind die Knopffunktionen im „Gehe“-Menü in den Punkten „Nächste“ und „Vorherige“ zu finden.
Um die Listen-Knöpfe gleichzeitig sowohl in Mozillas statischen als auch in Thunderbirds anpassbaren Werkzeugleisten anzeigen zu können, sind sie in eine eigene Datei ausgelagert und über den statischen overlay-Mechanismus wieder eingebunden. Die notwendigen CSS-Regeln für den Werkzeugleisten-Anpassungsdialog wurden dynamisch überlagert, siehe Listing 4b.
Listing 4a: content.contents.rdf
urn:mozilla:package:mistory wird das Paket mistory registriert. Zudem ĂĽberlagert eine Datei des Pakets die XUL-Datei mailWindowOverlay.xul dynamisch. Eine Stylesheet-Ăśberlagerung anstelle der ?xml-stylesheet?-Instruktion findet hier allerdings nicht statt.
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- package information -->
<RDF:Seq about="urn:mozilla:package:root">
<RDF:li>
<RDF:Description about="urn:mozilla:package:mistory"
chrome:name="mistory"
chrome:displayName="mistory - Message History"
chrome:versio="1.0.0.0"
chrome:author="Karsten Düsterloh <kd-mistory@tprac.de>"
chrome:authorURL="http://mnyromyr.de/"
chrome:description="Message history for Mail&News"
chrome:extension="true"
/>
</RDF:li>
</RDF:Seq>
<!-- overlay information: -->
<RDF:Seq about="urn:mozilla:overlays">
<RDF:li>
<RDF:Seq about="chrome://messenger/content/mailWindowOverlay.xul">
<RDF:li>chrome://mistory/content/mistory.xul</RDF:li>
</RDF:Seq>
</RDF:li>
</RDF:Seq>
</RDF:RDF>
Listing 4b: skin.contents.rdf
urn:mozilla:skin:classic/1.0:mistory erfolgt die Registrierung der Mistory-Erweiterung für das Classic-Theme (classic/1.0), die erst ab Version 1.5 des Themes gültig ist. Außerdem wird eine CSS-Datei des Pakets in eine vorhandene XUL-Datei eingefügt. Für Sprachpakete sieht die Struktur der entsprechenden contents.rdf ähnlich aus.
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<RDF:Seq about="urn:mozilla:skin:root">
<RDF:li>
<RDF:Description about="urn:mozilla:skin:classic/1.0">
<chrome:packages>
<RDF:Seq about="urn:mozilla:skin:classic/1.0:packages">
<RDF:li>
<RDF:Description about="urn:mozilla:skin:classic/1.0:mistory"
chrome:skinVersion="1.5"/>
</RDF:li>
</RDF:Seq>
</chrome:packages>
</RDF:Description>
</RDF:li>
</RDF:Seq>
<!-- Zusätzliche Stylesheets für Thunderbirds
anpassbare Werkzeugleisten -->
<RDF:Seq about="urn:mozilla:stylesheets">
<RDF:li>
<RDF:Seq about="chrome://global/content/customizeToolbar.xul">
<RDF:li>chrome://mistory/skin/mistory.css</RDF:li>
</RDF:Seq>
</RDF:li>
</RDF:Seq>
</RDF:RDF>
Neben den Style-Informationen fĂĽr die verschiedenen Themes Classic, Modern (Mozilla) und Qute (Thunderbird) stellt Mistory zudem Sprachdateien fĂĽr Englisch (en-US) und Deutsch (de-DE, de-AT) zur VerfĂĽgung.
Ausblick
Die Mozilla-Plattform bietet mit der XUL/XBL/Javascript/CSS-Kombination schon jetzt echtes Rapid Application Development (RAD), denn chrome-registrierte Pakete lassen sich auf der Kommandozeile über den Parameter -chrome chrome://paket/content/Hauptseite.xul unabhängig von Browser oder Mailer starten.
Wem Javascript zu langsam ist, beispielsweise bei der Berechnung längerer RSA-Schlüssel, der kann entweder auf Skriptebene über das Packages-Objekt auf eine vorhandene Java-Installation zurückgreifen oder sich eigene, nachinstallierbare C++-Komponenten schreiben.
XULs Entwicklung bleibt nicht stehen: Mit dem Vorankommen des XULRunner-Projekts (siehe „Online-Ressourcen“) machen die Entwickler einen weiteren großen Schritt in Richtung Einfachheit und Schnelligkeit in Planung und Aufbau grafischer Anwendungen. Es bleibt jedenfalls spannend, vor allem mit Blick auf die kommende Herausforderung durch Microsofts XAML.
Karsten DĂĽsterloh
ist Dipl.-Mathematiker und Entwickler bei tal.de sowie Autor der Mozilla-Erweiterung Mnenhy.
iX-TRACT
- Wie man Mozilla und Thunderbird erweitern kann, zeigt die Einbindung einer History-Funktion fĂĽr gelesene E-Mails und News.
- Voraussetzung fĂĽr die Erweiterung Mozilla-basierter Anwendungen ist die Kenntnis von XUL-Elementen wie broadcast, command und overlay.
- Damit Erweiterungen interne Schnittstellen aufrufen können, müssen sie über Chrome-Rechte verfügen.
Tutorialinhalt
- Teil I: Grundlegende Elemente wie window, button, menu und Attribute wie label et cetera.
- Teil II: Fortgeschrittene XUL-Elemente und Techniken wie Templates.
- Teil III: Mit XUL und Javascript Anwendungen wie Mozilla, Thunderbird und Firefox um eigene Funktionen erweitern.