Eine Chrome Extension mit REST-API Call

Das Grundgerüst der Chrome Erweiterung

In diesem und meinem ersten Beitrag, widmen wir uns dem Thema Chrome Extensions. Das Ziel dieses Tutorial ist es, eine simple Erweiterung für den Chrome Browser zu erstellen.
Die Chrome Extension soll ein zufälliges Zitat von tronalddump.io in einem neuen Tab anzeigen lassen. Fangen wir an.

Als erstes erzeugen wir einen neuen Projektordner. 
In unserem Projekt erstellen wir nun eine manifest.json Datei.

{
    "name" : "Random Tronalddump Quote",
    "description" : "Shows a random quote",
    "version" : "1.0",
    "manifest_version": 2,
}

Diese Zeilen stehen für folgendes:
name: Der Name der Erweiterung
description: Eine Beschreibung, die wie der Titel später im Browser angezeigt wird.
version: Die Version unserer Erweiterung.
manifest_version: Die Versionsnummer, des Manifests gibt an, wie der Browser die Spezifikationen innerhalb dieser Datei zu interpretieren hat.

Mit diesen vier Angaben haben wir genügend Informationen um eine Extension anzulegen. Allerdings ist der Funktionsumfang noch sehr begrenzt.
Das ändern wir jetzt.
Wir erzeugen eine index.html innerhalb unseres Projektordners, die eine Überschrift ausgibt.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Random Tronald</title>
    <script src="apicall.js"></script>
</head>
<body>
    <h1> Helloooo User</h1>
</body>
</html>

Die Html Datei allein und unsere aktuelle manifest.json Datei sind noch nicht ganz fertig.
Wir möchten, dass die HTML Datei beim Aufruf eines neuen Tabs geladen wird. Daher fehlt uns eine Definition dafür in dem Manifest unserer Chrome Extension.

{{
    "name" : "Random Tronalddump Quote",
    "description" : "Shows a random quote",
    "version" : "1.0",
    "chrome_url_overrides": {
        "newtab": "index.html"
    },
    "manifest_version": 2,
}

Mit der Angabe chrome_url_overrides können wir festlegen, dass unsere Extension, die Bookmarks, die History oder den New Tab mit einer von uns definierten Seite ersetzt.
Durch die Informationen „newtab“ und „index.html“ geben wir an, dass bei einem neuen Tab standardmäßig die index.html aufgerufen werden soll anstatt Beispielsweise eine vorausgewählte Website oder die Default Tab Page.

Wie aktivieren wir die Erweiterung aus unserem Chrome Extension Tutorial?

Nach dem Aufruf der Seite chrome://extensions/ haben wir die Möglichkeit den Entwicklermodus zu aktivieren und den Button „Entpackte Erweiterung laden“ zu betätigen. Wir wählen dann einfach unseren Projektordner aus.

Ist dies getan, wird uns die index.html beim Aufruf eines neuen Tabs angezeigt.

Erstellen des API Aufrufes

Soweit so gut. Nun möchten wir ein Zufälliges Zitat von tronalddump.io anzeigen lassen. Zufälligerweise existiert genau für unseren Fall eine solche Route in der tronalddump.io Api.

Erneut müssen wir einmal das Manifest unserer Chrome Erweiterung bearbeiten. Dieses mal müssen Permissions angelegt werden. (Stichwort CORS). Durch das hinuzfügen von einer Request cross-origin permission ist es möglich hosts anzugeben, auf die wir nun über remote Zugreifen können. Das heißt, wir können einen API Call ausführen.

{
    "name" : "Random Tronalddump Quote",
    "description" : "Shows a random quote",
    "version" : "1.0",
    "chrome_url_overrides": {
        "newtab": "index.html"
    },
    "manifest_version": 2,
    "permissions": [
        "*://*.tronalddump.io/*"
    ]
}

Wie allgemein üblich, steht auch hier das Asteriskzeichen als Wildcard zur Verfügung.

Für unseren Rest Api Call durch unsere Chrome Extension legen wir eine neue Javascript Datei an. Wir erstellen die apicall.js.


callTronald()

async function callTronald() {
    let url = 'https://api.tronalddump.io/random/quote'
    const response = await fetch(url, {
        method: 'GET',
        headers: {
            'Access-Control-Allow-Origin':'*'
            }
    }).then((data) => {
        return data.json()
    })

    console.log(response)
}

In unserer Javascript Datei erzeugen wir die Funktion callTronald().
In der Methode befindet sich die url Variable mit der Api Url.
Neben der url haben wir eine Konstante response, die den Rückgabe Wert der fetch Methode erwartet.
Von fetch() erhalten wir ein Promise, dass wir im then Zweig an response zurückgeben.

Da wir in einer asynchronen Funktion arbeiten, können wir die console.log Ausgabe mit unserer Response ausführen ohne ein Promise, sondern die zurückgegebenen Json Daten der API zu sehen.

Daher sollten wir im console Tab unserer Chrome Devtools, in einem neu geöffneten leeren Tab, den Rückgabewert des Api Aufrufes sehen.

Styling und Ausgeben der API-Daten

Wir bekommen nun die wertvollen Daten, die wir schon immer haben wollten und nun müssen wir sie nur noch präsentieren.

Daher widmen wir uns zunächst einmal unserer index.html und fügen einige neue Elemente in den Body des Dokuments ein.

<body>
    <div class="container">
            <h1>Got a Quote?</h1>
            <div class="quote-container">
                <p id="quote" class="font-weight-bold"></p>
                <p id="author"><a target="_blank" class="clean" href=""></a></p>
            </div>
            <a href="#" id="call-tronald">One more please!</a>
    </div>
</body>

Ein Div mit der Container Klasse und dadrinn eine Überschrift und ein weiterer Div mit den entsprechenden Nodes für die Daten, die wir darstellen möchten. Das Zitat, den Namen des Authors, sowie ein Link zur Quelle aus der das Zitat stammt.

Wie zu erkennen ist verwenden wir ids und classes. Diese für das Styling und die Ansprache durch das Javascript. Zunächst erstellen wir ein <style> Element im Head Bereich unserer Html Seite und fügen dort ein wenig CSS ein.

body {
  width: 100vw;
  padding: 0;
  margin: 0;
}
.container {
  height: 20vh;
  min-height: 300px;
  width: 50%;
  max-width: 650px;
  padding: 8% 5% 5% 5%;
  margin: auto;
}
.container > * {
  text-align: center;
}

#call-tronald {
  text-decoration: none;
  padding: 5px;
  border: 1px solid #000;
  border-radius: 5px;
  font-size: 14px;
  color: #fff;
  font-weight: 600;
  display: block;
  margin: auto;
  height: 20px;
  width: 120px;
}

#call-tronald:hover {
  background-color: #000;
  color: #fff;
}

.font-weight-bold {
  font-weight: bold;
}
#quote {
  min-height: 50px;
  margin-top: 20px;
}
#author {
  margin-top: 10px;
}
.clean,
.clean:hover {
  color: #000;
  text-decoration: none;
}

Auch in der Javascript Datei müssen wir noch einige Änderungen vornehmen. Wir möchten ja die Platzhalterelemente in unserer Html Datei mit Daten befüllen und den Button betätigen können um ein neues Zitat anzufordern.

async function callTronald() {
  let url = "https://api.tronalddump.io/random/quote";
  const response = await fetch(url, {
    method: "GET",
    headers: {
      "Access-Control-Allow-Origin": "*"
    }
  }).then(data => {
    return data.json();
  });
  document.getElementById("quote").innerText = response.value;
  document.querySelector("#author a").innerHTML =
    response._embedded.author[0].name;
  document.querySelector("#author a").href = response._embedded.source[0].url;
}

Nach unserem API Call fragen wir durch document.getElementById die Elemente mit den ids quote und mit Hilfe von document.querySelector den Link im author Element ab.
Diese erhalten dann die jeweiligen Werte aus unserer tronalddump.io API Abfrage.
Der function call callTronald() wurde am Anfang des Dokumentes entfernt.
Da wir nun zwei Listener unterhalb der callTronald() Methode einfügen.

// LISTENER
document.addEventListener("DOMContentLoaded", function() {
  callTronald()
  document
    .getElementById("call-tronald")
    .addEventListener("click", callTronald);
});

Wir haben einen EventListener, der darauf wartet, dass die Inhalte des Doms vollständig geladen sind.
Wenn das Event DOMContentLoaded ausgelöst wird, ist unser Tab geladen und wir lösen initiierend die Methode callTronald() aus, damit das erste Zitat direkt geladen wird.
Anschließend wird ein weiterer EventListener registriert, der darauf wartet, dass unser Link-Button mit der id call-tronald geclickt wird. Wenn dises Event ausgelöst wird, wird ebenfalls die Methode callTronald angewendet.

Zum Schluss einmal alle drei vollständigen Dateien.

{
    "name" : "Random Tronalddump Quote",
    "description" : "Shows a random quote",
    "version" : "1.0",
    "chrome_url_overrides": {
        "newtab": "index.html"
    },
    "manifest_version": 2,
    "permissions": [
        "*://*.tronalddump.io/*"
    ]
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Random Tronald</title>
    <script src="apicall.js"></script>

    <style>
      body {
        width: 100vw;
        padding: 0;
        margin: 0;
      }
      .container {
        height: 20vh;
        min-height: 300px;
        width: 50%;
        max-width: 650px;
        padding: 8% 5% 5% 5%;
        margin: auto;
      }
      .container > * {
        text-align: center;
      }

      #call-tronald {
        text-decoration: none;
        padding: 5px;
        border: 1px solid #000;
        border-radius: 5px;
        font-size: 14px;
        color: #fff;
        font-weight: 600;
        display: block;
        margin: auto;
        height: 20px;
        width: 120px;
      }

      #call-tronald:hover {
        background-color: #000;
        color: #fff;
      }

      .font-weight-bold {
        font-weight: bold;
      }
      #quote {
        min-height: 50px;
        margin-top: 20px;
      }
      #author {
        margin-top: 10px;
      }
      .clean,
      .clean:hover {
        color: #000;
        text-decoration: none;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1>Got a Quote?</h1>
      <div class="quote-container">
        <p id="quote" class="font-weight-bold"></p>
        <p id="author"><a target="_blank" class="clean" href=""></a></p>
      </div>
      <a href="#" id="call-tronald">One more please!</a>
    </div>
  </body>
</html>
async function callTronald() {
  let url = "https://api.tronalddump.io/random/quote";
  const response = await fetch(url, {
    method: "GET",
    headers: {
      "Access-Control-Allow-Origin": "*"
    }
  }).then(data => {
    return data.json();
  });
  document.getElementById("quote").innerText = response.value;
  document.querySelector("#author a").innerHTML =
    response._embedded.author[0].name;
  document.querySelector("#author a").href = response._embedded.source[0].url;
}
// LISTENER
document.addEventListener("DOMContentLoaded", function() {
  callTronald();
  document
    .getElementById("call-tronald")
    .addEventListener("click", callTronald);
});

Und so sollte der neue Tab dann aussehen. Ziemlich nice oder?

Für weitere Lektüre und Beispiele empfiehlt sich natürlich auch die offizielle Dokumentation hierzu.

Die Chrome Erweiterung ist auch im Chrome Web Store verfügbar.
Eine Bewertung der Extension im Store würde mich freuen.

Schreibe einen Kommentar