First Web Extension | Stardew Wiki search box modification
This is the first web extension I made. I've made one for the minecraft wiki as well (same thing), but I haven't released either one. You might have to fix some bugs... I threw this together in a pretty short amount of time & I'm just leaving it as is. Hopefully this is a better experience than reading up on web-extensions to figure out how to do simple things.
The UI for this WebExtension is non-traditional. That means you're loading a popup into the document, instead of using the built-in GUI methods for web extensions. I'm not well-versed on Mozilla or Google's policies on WebExtensions, so I don't know if you can release such a thing, but... It's cool anyway.
We'll build a simple control panel overlay for Stardew Valley Wiki. The search box on the page will be added to a position:fixed
div & that search box will be focused everytime a wiki page is loaded or focused. (alt+tab from one app back to the browser)
1. Create the skeleton
- Create a directory named
rbear-stardew
. Perhaps inDocuments/Firefox Extensions
or inside your usual code workspace, or any other directory of your choice. - Create files as follows (content to follow):
rbear-stardew - manifest.json //extension settings | view - panel.html //html for the control panel | script - init-panel.js //to set everything up - RB-Request.js //to help with sending requests - functions.js //helper functions for adding files to the page | style - panel.css //style the control panel
2. Add code to all the files
manifest.json
The manifest.json
contains all the settings for the extension.
Pay special attention to content_scripts
and web_accessible_resources
.
{
"manifest_version": 2,
"name": "StardewValleyWiki Panel",
"version": "1.0",
"description": "Adds a (bad) control panel to StardewValleyWiki.com",
"content_scripts": [
{
"matches": [
"*://stardewvalleywiki.com/*"
],
"js": [
"/script/RB-Request.js",
"/script/functions.js",
"/script/init-panel.js"
]
}
],
"web_accessible_resources": ["style/panel.css","view/panel.html"]
}
The order of the scripts in content_scripts
is very important. Those scripts are loaded in the order they're listed & init-panel.js
needs the prior two scripts to be loaded already.
view/panel.html
This is a very simple panel which will float on top of the page, thanks to style/panel.css
.
<div id="rbear_wiki_panel">
<h6>Control Panel</h6>
</div>
style/panel.css
This makes your HTML panel float. & it's super ugly.
#rbear_wiki_panel {
background:rgba(0,0,0,0.4);
position:fixed;
right:0;
top:0;
width:250px;
height:200px;
}
script/init-panel.js
This will set everything up. Note that it depends upon RB-Request.js
and functions.js
(see below)
function focusSearch(){
const searchInput = document.getElementById("searchInput"); //pre-existing component on the StardewWiki
searchInput.focus();
};
function doSetup(){
const cssUrl = browser.runtime.getURL('/style/panel.css');
loadStyle(cssUrl);
const viewUrl = browser.runtime.getURL('/view/panel.html');
const request = new RB.Request(viewUrl);
request.handleText(function(rawHtml){
loadHtmlString(rawHtml);
const form = document.getElementById("searchform"); //pre-existing component on the StardewWiki
form.parentNode.removeChild(form);
const wikiPanel = document.getElementById("rbear_wiki_panel"); //prefix, to avoid collisions with resources on the site.
wikiPanel.appendChild(form); //moved the searchform from the page as normal over to the floating panel
focusSearch();
});
}
window.addEventListener("focus",focusSearch); //so the search bar gets focus every time the page is focused
document.body.addEventListener("load",doSetup); //in case the body isn't loaded yet...
doSetup(); //the body probably is already loaded, so 'load' won't be called. This is a bad approach.
You can see we call loadStyle(cssUrl)
above. This is because, if we embed a <link>
inside /view/panel.html
, it will load stardewvalleywiki.com/view/panel.html
, since the html is being added to the main document's body. There are probably better ways to handle this.
script/RB-Request.js
Get an up-to-date crummy Request class on github.
if (typeof RB === 'undefined')var RB = {};
RB.Request = class {
constructor(url, method){
this.params = {};
this.url = url;
this.method = method ?? 'POST';
}
put(key,value){
if (key in this.params){
this.params[key] = (typeof this.params[key]==typeof []) ? this.params[key] : [this.params[key]];
this.params[key].push(value);
} else {
this.params[key] = value;
}
}
handleJson(func){
var formData = new FormData();
for(var key in this.params){
const param = this.params[key];
if (typeof param == typeof []){
for(const val of param){
formData.append(key,val);
}
} else formData.append(key,this.params[key]);
}
fetch(this.url, {
method: this.method,
mode: "cors",
body: formData
}).then(res => {
return res.json();
}).then(json => {
func(json);
});
}
handleText(func){
var formData = new FormData();
for(var key in this.params){
const param = this.params[key];
if (typeof param == typeof []){
for(const val of param){
formData.append(key,val);
}
} else formData.append(key,this.params[key]);
}
fetch(this.url, {
method: this.method,
mode: "cors",
body: formData
}).then(res => {
return res.text();
}).then(text => {
func(text);
});
}
}
script/functions.js
function loadStyle(href){
// avoid duplicates
for(var i = 0; i < document.styleSheets.length; i++){
if(document.styleSheets[i].href == href){
return;
}
}
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = href;
head.appendChild(link);
}
function loadHtmlString(html,parentNode = 'document.body'){
if (parentNode==='document.body')parentNode = document.body;
var wrapper = document.createElement('div'); //you could use a span here, if you want inline-styling, or customize styles through js.
wrapper.innerHTML = html;
parentNode.appendChild(wrapper);
}
3. Run the extension
- Open https://stardewvalleywiki.com in Firefox & look at the search bar in the top-right
- Go to
about:debugging
in a new tab (type that into the url bar) - click 'This Firefox'
- click 'Load Temporary Addon'
- Choose the 'manifest.json' of your extension
- Refresh the Stardew wiki page.
- Click on the page (so search bar not focused).
- Alt+tab to a different program, then alt+tab back & type "tractor" (or whatever)