Opera Erweiterungen

Permalink

Bei jeder Software kommt man an den Punkt wo man denkt: “Warum kann die das jetzt nicht?”. Bei Opera kann man bei Funktionen die man vermisst eine Erweiterung installieren oder eine eigene Schreiben. Wenn man letzteres Vorhat sollte man sich mit Javascript beschäftigen – nichts anderes sind diese Erweiterungen hauptsächlich.

Aufgabenstellung

Als einfaches Beispiel für meine ersten Versuche möchte ich einen QR-Code-Generator erstellen der zur Webseite im aktuellen Tab, beziehungsweise deren URL, einen QR-Code anzeigt. Der QR-Code soll dabei von einem Webdienst, wie QR-Server, erzeugt und von dort eingebunden werden.

Artefakte

In einer Opera-Erweiterung gibt es fünf Arten von Dingen die man programmieren kann. Den Background-Prozess, Buttons, Popups, Injected Scripts und Einstellungsdialoge. Der Background-Prozess steuert die gesamte Funktionalität. Mit Buttons und in Popups wird die Benutzeroberfläche des Plugins realisiert. Mittels ‘eingeschleuster’ Scripte kann man sich in den angezeigten Webseiten austoben, alles was damit oder darin gemacht werden soll wird in einer solchen Javascriptdatei umgesetzt.

Von eher deklarativer Natur ist die Datei config.xml. Hier werden Name, Autor, Versionsnummer und andere Informationen abgelegt.

Der Background-Prozess

Das Herz einer jeden Erweiterung, es übernimmt die Initialisierung, erzeugt die Oberflächenelemente wie Buttons und Popups und ist der Mittelpunkt der meisten Kommunikation. Umso erstaunlicher erscheint es auf den ersten Blick das es sich um eine schlichte HTML-Seite namens index.html handelt. Eigentlich spielt HTML hier aber gar keine Rolle außer um ein Script-Tag unterzubringen in dem der Code der Erweiterung unterkommt.

<!doctype html>
<html>
  <head>
    <title>Name der Erweiterung</title>
    <script>
      // Hier steht der Code der Erweiterung		
    </script>
  </head>
  <body></body>
</html>

Buttons

Screenshot eines Buttons Buttons sind Schaltflächen die rechts neben der Adresszeile angezeigt werden und zwei Funktionen haben. Einerseits können sie Popups öffnen und andererseits beliebigen Javascriptcode ausführen wenn man sie betätigt.

Buttons sind reine Javascriptobjekte die im Backgrundprozess angelegt werden können. Zur optischen Gestaltung verfügt jeder Button über ein Icon einen Text und optional eine Markierung ober rechts in der Ecke.

var UIItemProperties = {
   disabled: false,
   title: "QR-Code",
   icon: "qro.png",
   onclick: function() {
      //Hier steht der Code der beim Click ausgeführt wird
   },
   popup: {
      href: "popup.html",
      width: 240,
      height: 260
   }
}
var theButton = opera.contexts.toolbar.createItem( UIItemProperties );
opera.contexts.toolbar.addItem( theButton );

Popups

Screenshot eines Popups Einem Button lässt sich eine Sprechblase zuordnen. Diese wird unterhalb des Buttons angezeigt wenn man auf diesen klickt. Opera nennt diese Sprechblasen Popups. Technisch sind Popups HTML-Seiten. Die Oberfläche wird also mit den Fähigkeiten von Opera im Bereich HTML und CSS gestaltet. Alle dynamischen Abläufe und Benutzerinteraktion werden mit Javascript realisiert.

<!doctype html>

<html lang="en">
   <head>
      <title>QRO</title>
      <script>
         // Alles was das Popup tun soll hier hinein
      </script>
   </head>
   <body>
      <p>
         <a style="display:none;" id="qrlink" href='#'>
          <img id="qrimage" src='qro.png' alt='QR Code' style="height: 200px; width: 200px">
         </a>
      </p>
   </body>
</html>

Injected Scripts

Damit eine Erweiterung etwas mit den in Opera angezeigten Webseiten anstellen kann muss sie Javascript im Kontext dieser Seiten ausführen können, Zu diesem Zweck werden Injected Scripts eingesetzt. Solche Javascriptdateien müssen im Ordner includes der Erweiterung gespeichert werden und aktivieren sich automatisch beim Laden einer Erweiterung.

Diese Art von Scripten unterstützt die selben Funktionen wie die schon länger nutzbaren User Scripts. Solche eigenen sich daher auch als Inspiration.

Einstellungsdialoge

Um ein Plugin konfigurieren zu können benötigt man eine entsprechende Oberfläche. Bei Opera wird diese durch eine HTML-Datei namens options.html definiert. In dieser werden mittels Formularelementen passende Eingabemöglichkeiten erzeugt. Die jeweiligen Werte werden mittels Javascript in den Properties des Plugins gespeichert. Diese Properties sind ein Key-Value-Store. Das heißt unter einem Namen wird ein Wert abgespeichert und kann über diesen Namen auch wieder abgerufen werden:

<fieldset>
  <legend>QR-Code Preferences</legend>
  <p>
    <label for="qrsize">Size in Pixel</label>:
    <input id="qrsize" name="qrsize" type="range" min="10" max="700" step="10" value="200"></input>
    <span id="resolution">200</span>
  </p>
</fieldset>
<script>
function showResolution(newValue) {
  document.getElementById("resolution").innerHTML=newValue+'&times;'+newValue+'px';
}

function changedSize( e ) {
  // set value
  widget.preferences.setItem( this.name, this.value );
  showResolution(this.value);

  opera.extension.postMessage({'event':'changePreference', 'name':this.name, 'value':this.value});	
}

addEventListener('DOMContentLoaded', function() {
    var storage = widget.preferences; 
    var sizeSettingElement = document.getElementById("qrsize");

    // Wert aus Properties beim Initialisieren setzen
    if (storage.getItem( sizeSettingElement.name )) {
      sizeSettingElement.value = storage[ sizeSettingElement.name ];
      showResolution( sizeSettingElement.value );
    }
    else {
      storage.setItem( element.name, element.value );
    }

    // listen to changes
    sizeSettingElement.addEventListener( 'change', changedSize, true );
  }, false
);
</script>

Kommunikation

Damit die oben beschriebenen Komponenten Daten austauschen können gibt es ein Messaging-API. Hiermit lassen sich Nachrichten zwischen dem Backgroundprozess, den Popups und den Injected Scripts austauschen.

Mit der API kann man entweder seine Informationen hinausbrüllen und mit broadcastMessage("your Message") alle anderen Komponenten auf einmal erreichen oder man geht etwas gezielter vor und öffnet einen direkten Kanal zwischen zwei Punkten. Am einfachsten geht das wenn man eine Botschaft zum Backgroundprozess schicken möchte:

opera.extension.postMessage("sending something");

opera.extension ist dabei eine Referenz auf den Backgroundprozess die immer zur Verfügung steht.

In die andere Richtung geht es natürlich auch:

target.postMessage("sending something");

Diese Anweisung sendet einen Text an das Objekt target.

Externe Resourcen

Um externe Ressourcen wie Webservices oder Bilder aus der Erweiterung aufrufen zu können muss man dies speziell in der config.xml anmelden. Mittels eines Access-Tags gibt man an auf welche Domain man zugreifen möchte. Verschiedene Domains muss man jeweils mit einem eigenen Tag angeben.

<access origin="http://api.qrserver.com" />

Packaging

Eine Erweiterung kann man auf zwei Arten in Opera installieren: Während der Entwicklung reicht es aus die config.xml mit der Maus aus dem Dateiexplorer auf ein Opera-Fenster zieht. Dieser Vorgang aktiviert die Erweiterung im Entwicklungsmodus. Später, wenn man glaubt soweit zu sein, kann man alle Dateien in ein Zip-Archive packen und dessen Endung auf oex enden. OEX-Dateien sind mit Opera-Verknüpft, sie installieren sich also mit einem Doppelklick oder beim Herunterladen. Man kann sie also auf der eigenen Webseite zum Download anbieten.

Übung macht den Meister

Die obigen Beispiele entstammen aus meinem kleinen Kennenlernprojekt. Die Aufgabenstellung dabei war es einen Generator zu erstellen, der zur Adresse der Webseite im aktuellen Tab einen QR-Code anzeigt. Der Code sollte dabei von einem Webdienst wie QR-Server erzeugt und von dort eingebunden werden.

Die gesamte Extension, ich habe sie QRO genannt, kann man sich gerne herunterladen und ausprobieren.Wer möchte darf sich auch gerne daran versuchen meinen eigenen Versuch zu verbessern.

Abschlussbemerkung

Wer schon Erfahrung mir HTML und insbesondere Javascript hat erhält mit Operas Erweiterungen eine einfach zu erlernende Möglichkeit seine individuellen Vorstellungen von dem was ein Browser können sollte umzusetzen.