1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
---
title: Deine zweite Erweiterung
slug: Mozilla/Add-ons/WebExtensions/Your_second_WebExtension
translation_of: Mozilla/Add-ons/WebExtensions/Your_second_WebExtension
original_slug: Mozilla/Add-ons/WebExtensions/Deine_zweite_Erweiterung
---
<p>{{AddonSidebar}}</p>
<p>Wenn du den Artikel "<a href="https://developer.mozilla.org/de/Add-ons/WebExtensions/Deine_erste_WebErweiterung">Deine erste Erweiterung</a>" gelesen hast, hast du schon eine Vorstellung, wie man eine Erweiterung schreibt. In diesem Artikel werden wir eine komplexere Erweiterung schreiben, die mehr APIs benutzt.</p>
<p>Die Erweiterung fügt eine neue Schaltfläche zu Firefox hinzu. Wenn der Nutzer diese anklickt, wird ihm ein Popup angezeigt auf dem er ein Tier auswählen kann. Sobald er eines ausgewählt hat, wird der aktulle Inhalt der Website mit dem Bild des ausgewählten Tieres ersetzt.</p>
<p>Um das zu implementieren werden wir:</p>
<ul>
<li><strong>eine <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action">Browser-Aktion</a> definieren, die zur Firefox-Toolbar hinzugefügt werden wird.</strong><br>
Für die Schaltfläche benötigen wir:
<ul>
<li>ein Icon namens "beasts-32.png"</li>
<li>Ein Popup welches sich öffnet, sobald der Nutzer auf die Schaltfläche klickt. Das Popup wird <a href="https://developer.mozilla.org/de/docs/Glossary/HTML">HTML</a>, <a href="https://developer.mozilla.org/de/docs/Glossary/CSS">CSS</a>, und <a href="https://developer.mozilla.org/de/docs/Glossary/JavaScript">JavaScript</a> beinhalten.</li>
</ul>
</li>
<li><strong>ein Icon festlegen</strong>, genannt "beasts-48.png". Dieses wird im Addon-Manager angezeigt werden.</li>
<li><strong>Ein content-script "beastify.js" schreiben, welches auf Webseiten angezeigt werden wird.</strong><br>
Das ist der Code, der letztendlich die Webseite verändert.</li>
<li><strong>Einige Tier-Bilder einfügen, um die Bilder auf der Webseite zu ersetzen</strong><br>
Die Bilder werden "web-abrufbare Ressourcen" werden, sodass die Webseite sie abrufen kann.</li>
</ul>
<p>Man kann die Struktur der Erweiterung wie folgt darstellen:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13671/Untitled-1.png" style="display: block; height: 1200px; margin-left: auto; margin-right: auto; width: 860px;"></p>
<p>Es ist eine einfache Erweiterung, aber es zeigt viele der Grundkonzepte der WebExtensions API:</p>
<ul>
<li>Hinzufügen einer Schaltfläche zur Toolbar</li>
<li>Erstellen eines Popup-Menüs mit HTML, CSS, und JavaScript</li>
<li>Verändern des Webseiteninhalts</li>
<li>Kommunikation zwischen dem content-script und dem Rest der Erweiterung</li>
<li>Verpacken von Ressourcen, die später auf der Webseite genutzt werden können.</li>
</ul>
<p>Der <a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">komplette Quellcode der Erweiterung</a> ist auf GitHub zu finden.</p>
<p>Um die Erweiterung zu erstellen, brauchst du mindestens Firefox 45.</p>
<h2 id="Die_Erweiterung_schreiben">Die Erweiterung schreiben</h2>
<p>Erstelle einen neuen Ordner und öffne ihn:</p>
<pre class="brush: bash">mkdir beastify
cd beastify</pre>
<h3 id="manifest.json">manifest.json</h3>
<p>Erstelle jetzt eine Datei namens "manifest.json" und füge den folgenden Inhalt ein:</p>
<pre class="brush: json">{
"manifest_version": 2,
"name": "Beastify",
"version": "1.0",
"description": "Erstellt eine Schaltfläche in der Toolbar. Klicke auf eine der Schaltflächen, um ein Tier auszuwählen. Der Inhalt des gerade geöffneten Tabs wird dann mit dem Bild des ausgewählten Tieres ersetzt. Nachschlagen: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#beastify",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
"icons": {
"48": "icons/beasts-48.png"
},
"permissions": [
"activeTab"
],
"browser_action": {
"default_icon": "icons/beasts-32.png",
"default_title": "Beastify",
"default_popup": "popup/choose_beast.html"
},
"web_accessible_resources": [
"beasts/frog.jpg",
"beasts/turtle.jpg",
"beasts/snake.jpg"
]
}
</pre>
<ul>
<li>Die ersten drei Eigenschaften <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/manifest_version">manifest_version</a></code>, <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/name">name</a></code>, und <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/version">version</a></code> sind erforderlich und enthalten Basismetadaten.</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/description">description</a></code> und <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/homepage_url">homepage_url</a></code> sind optional aber empfohlen, sie erhalten nützliche Informationen.</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/icons">icons</a></code> ist optional aber empfohlen, hier kannst du ein Icon festlegen, welches im Addon-Manager angezeigt werden wird.</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> listet die Berechtigungen auf, die die Erweiterung benötigt. Hier brauchen wir nur die <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission">activeTab Berechtigung</a>.</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> spezifiziert die Schaltfläche. Hier übergeben wir drei Informationen:
<ul>
<li><code>default_icon</code> ist notwendig, und gibt das Icon der Schaltfläche an</li>
<li><code>default_title</code> ist optional und wird unter dem Icon angezeigt</li>
<li><code>default_popup</code> wird verwendet, wenn ein Popup angezeigt werden soll, sobald der Nutzer auf die Schaltfläche klickt. Das soll so sein, deshalb wird hier die Eigenschaft mit einer HTML-Datei belegt.</li>
</ul>
</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources">web_accessible_resources</a></code> listet die Dateien auf, die auf Webseiten verwendet werden solllen. Weil die Erweiterung den Inhalt der Webseite mit den Bilder, die der Erweiterung hinzugefügt wurden, verändern soll, müssen die Bilder hier aufgelistet werden.</li>
</ul>
<p>Beachte, dass alle Pfade relativ zur manifest.json angegeben werden.</p>
<h3 id="Das_Icon">Das Icon</h3>
<p>Die Erweiterung soll ein Icon beinhalten, das neben dem Eintrag der Erweiterung in der Add-ons-Verwaltung angezeigt wird (diese kannst du durch Aufrufen der URL "about:addons" öffnen). In manifest.json haben wir festgelegt, dass wir ein Icon für die Toolbar unter "icons/beasts-48.png" bereitstellen.</p>
<p>Erstelle das "icons"-Verzeichnis and speichere dort das Icon namens "beasts-48.png". Du kannst das <a href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-48.png">Icon aus unserem Beispiel</a> verwenden, welches aus dem <a href="https://www.iconfinder.com/iconsets/free-retina-icon-set">Aha-Soft’s Free Retina Icon-Set</a> stammt und gemäß seiner <a href="http://www.aha-soft.com/free-icons/free-retina-icon-set/">Lizenzbestimmungen</a> genutzt wird.</p>
<p>Wenn du dich entscheidest, ein eigenes Icon zu verwenden, sollte es eine Auflösung von 48x48 Pixeln besitzen. Zusätzlich kannst du ein 96x96 Pixel großes Icon für hochaufgelöste Bildschirme bereitstellen. In diesem Fall wird es unter der Eigenschaft <code>96</code> des <code>icons</code> Objekts in manifest.json aufgeführt:</p>
<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"icons":</span> <span class="punctuation token">{</span>
<span class="key token">"48":</span> <span class="string token">"icons/beasts-48.png"</span><span class="punctuation token">,</span>
<span class="key token">"96":</span> <span class="string token">"icons/beasts-96.png"</span>
<span class="punctuation token">}</span></code></pre>
<h3 id="Die_Toolbar-Schaltfläche">Die Toolbar-Schaltfläche</h3>
<p>Die Toolbar-Schaltfläche benötigt ebenfalls ein Icon, das laut unserer manifest.json unter "icons/beasts-32.png" bereitsteht.</p>
<p>Speichere ein Icon namens "beasts-32.png" im Verzeichnis "icons".Du kannst das <a href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-32.png">Icon aus unserem Beispiel</a> verwenden, welches aus dem <a href="http://www.iconbeast.com/free">IconBeast Lite Icon-Set</a> stammt und gemäß seiner <a href="http://www.iconbeast.com/faq/">Lizenzbestimmungen</a> genutzt wird.</p>
<p>Wenn du kein Popup einsetzt, dann wird ein Klick-Event zur Erweiterung gesendet, sobald der Benutzer die Schaltfläche anklickt. Wenn du hingegen ein Popup einsetzt, wird dieses Klick-Event nicht gesendet, sondern das Popup wird geöffnet. Da wir ein Popup verwenden wollen, soll dieses im nächsten Schritt erstellt werden.</p>
<h3 id="Das_Popup">Das Popup</h3>
<p>Mithilfe des Popups soll der Benutzer eines von drei Tieren auswählen können.</p>
<p>Erstelle ein neues Verzeichnis namens "popup" in der obersten Ebene des Erweiterungsverzeichnisses. Dieses Verzeichnis wird den Code für das Popup enthalten. Das Popup besteht aus drei Dateien:</p>
<ul>
<li><strong><code>choose_beast.html</code></strong> legt den Inhalt des Fensters fest</li>
<li><strong><code>choose_beast.css</code></strong> legt das Styling des Fensters fest</li>
<li><strong><code>choose_beast.js</code></strong> verarbeitet die Auswahl des Benutzers, indem es im aktiven Tab ein Content Script ausführt</li>
</ul>
<h4 id="choose_beast.html">choose_beast.html</h4>
<p>Die HTML-Datei sieht folgendermaßen aus:</p>
<pre class="brush: html"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="choose_beast.css"/>
</head>
<body>
<div class="button beast">Frog</div>
<div class="button beast">Turtle</div>
<div class="button beast">Snake</div>
<div class="button clear">Reset</div>
<script src="choose_beast.js"></script>
</body>
</html></pre>
<p>Es gibt ein Element für jedes Tier. Beachte, dass in dieser Datei auch die CSS- und JavaScript-Dateien verlinkt werden, genau wie auf einer Website.</p>
<h4 id="choose_beast.css">choose_beast.css</h4>
<p>Die CSS-Datei legt die Größe des Popups fest, stellt sicher, dass die drei Auswahlmöglichkeiten, den verfügbaren Platz ausfüllen und legt das grundlegende Styling fest:</p>
<pre class="brush: css">html, body {
width: 100px;
}
.button {
margin: 3% auto;
padding: 4px;
text-align: center;
font-size: 1.5em;
cursor: pointer;
}
.beast:hover {
background-color: #CFF2F2;
}
.beast {
background-color: #E5F2F2;
}
.clear {
background-color: #FBFBC9;
}
.clear:hover {
background-color: #EAEAC9;
}
</pre>
<h4 id="choose_beast.js">choose_beast.js</h4>
<p>In der JavaScript-Datei des Popups empfangen wir Klick-Events. Wenn ein Klick auf eines der Tiere erfolgte, wird das Content Script zum aktiven Tab hinzugefügt. Sobald das Content Script geladen wird, übergeben wir ihm eine Nachricht mit der Auswahl des Tieres:</p>
<pre class="brush: js">/*
Given the name of a beast, get the URL to the corresponding image.
*/
function beastNameToURL(beastName) {
switch (beastName) {
case "Frog":
return browser.extension.getURL("beasts/frog.jpg");
case "Snake":
return browser.extension.getURL("beasts/snake.jpg");
case "Turtle":
return browser.extension.getURL("beasts/turtle.jpg");
}
}
/*
Listen for clicks in the popup.
If the click is on one of the beasts:
Inject the "beastify.js" content script in the active tab.
Then get the active tab and send "beastify.js" a message
containing the URL to the chosen beast's image.
If it's on a button which contains class "clear":
Reload the page.
Close the popup. This is needed, as the content script malfunctions after page reloads.
*/
document.addEventListener("click", (e) => {
if (e.target.classList.contains("beast")) {
var chosenBeast = e.target.textContent;
var chosenBeastURL = beastNameToURL(chosenBeast);
browser.tabs.executeScript(null, {
file: "/content_scripts/beastify.js"
});
var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
gettingActiveTab.then((tabs) => {
browser.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL});
});
}
else if (e.target.classList.contains("clear")) {
browser.tabs.reload();
window.close();
}
});
</pre>
<p>It uses three WebExtensions API functions:</p>
<ul>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">browser.tabs.executeScript</a></code> to inject a content script found at "content_scripts/beastify.js" into the active tab</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query">browser.tabs.query</a></code> to get the active tab</li>
<li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">browser.tabs.sendMessage</a></code> to send a message to content scripts running in the active tab. The message contains the URL to an image of the chosen beast.</li>
</ul>
<h3 id="The_content_script">The content script</h3>
<p>Create a new directory, under the extension root, called "content_scripts" and create a new file in it called "beastify.js", with the following contents:</p>
<pre class="brush: js">/*
beastify():
* removes every node in the document.body,
* then inserts the chosen beast
* then removes itself as a listener
*/
function beastify(request, sender, sendResponse) {
removeEverything();
insertBeast(request.beastURL);
browser.runtime.onMessage.removeListener(beastify);
}
/*
Remove every node under document.body
*/
function removeEverything() {
while (document.body.firstChild) {
document.body.firstChild.remove();
}
}
/*
Given a URL to a beast image, create and style an IMG node pointing to
that image, then insert the node into the document.
*/
function insertBeast(beastURL) {
var beastImage = document.createElement("img");
beastImage.setAttribute("src", beastURL);
beastImage.setAttribute("style", "width: 100vw");
beastImage.setAttribute("style", "height: 100vh");
document.body.appendChild(beastImage);
}
/*
Assign beastify() as a listener for messages from the extension.
*/
browser.runtime.onMessage.addListener(beastify);
</pre>
<p>The content script adds a listener to messages from the extension (specifically, from "choose_beast.js" above). In the listener, it:</p>
<ul>
<li>removes every element in the <code>document.body</code></li>
<li>creates an <code><img></code> element pointing to the given URL, and inserts it into the DOM</li>
<li>removes the message listener.</li>
</ul>
<h3 id="The_beasts">The beasts</h3>
<p>Finally, we need to include the images of the animals.</p>
<p>Create a new directory called "beasts", and add the three images in that directory, with the appropriate names. You can get the images from <a href="https://github.com/mdn/webextensions-examples/tree/master/beastify/beasts">the GitHub repository</a>, or from here:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/11459/frog.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"><img alt="" src="https://mdn.mozillademos.org/files/11461/snake.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"><img alt="" src="https://mdn.mozillademos.org/files/11463/turtle.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"></p>
<h2 id="Testing_it_out">Testing it out</h2>
<p>First, double check that you have the right files in the right places:</p>
<pre>beastify/
beasts/
frog.jpg
snake.jpg
turtle.jpg
content_scripts/
beastify.js
icons/
beasts-32.png
beasts-48.png
popup/
choose_beast.css
choose_beast.html
choose_beast.js
manifest.json</pre>
<p>Starting in Firefox 45, you can install extensions temporarily from disk.</p>
<p>Open "about:debugging" in Firefox, click "Load Temporary Add-on", and select your manifest.json file. You should then see the extension's icon appear in the Firefox toolbar:</p>
<p>{{EmbedYouTube("sAM78GU4P34")}}</p>
<p>Open a web page, then click the icon, select a beast, and see the web page change:</p>
<p>{{EmbedYouTube("YMQXyAQSiE8")}}</p>
<h2 id="Developing_from_the_command_line">Developing from the command line</h2>
<p>You can automate the temporary installation step by using the <a href="/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext">web-ext</a> tool. Try this:</p>
<pre class="brush: bash">cd beastify
web-ext run</pre>
|