I'm learning how to make an extension (for Firefox).
This add-on reads the youtube main page (https://www.youtube.com/
) and get the visible videos on it. From those videos, I'm able to extract the video ID, title, duration of the video, channel name and channel ID.
With this data, I want to show a pop-up dialog with a HTML table that has the obtained info as folows:
Channel | No. of videos |
---|---|
NationSquid | 1 |
Numberphile | 4 |
JhonNroses | 8 |
HugoX Chugox | 3 |
[...and so on]
My manifest.json
:
{
"manifest_version": 2,
"name": "Ejemplo",
"version": "1.0",
"description": "Inspeccionar elementos de youtube.com.",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/main/beastify",
"icons": {
"48": "icons/border-48.png"
},
"applications": {
"gecko": {
"id": "manhunter45a45@example.com"
}
},
"permissions": [
"tabs",
"activeTab",
"storage",
"background"
],
"browser_action": {
"default_icon": "icons/beasts-32.png",
"default_title": "Obtain YouTube Info",
"default_popup": "popup/results.html",
"browser_style": true
},
"content_scripts": [
{
"matches": [
"https://*.youtube.com/"
],
"js": [
"jquery-1.9.1.min.js",
"Ejemplo.js",
"/code/functions.js"
]
}
],
"background": {
"scripts": [
"/code/popup.js"
]
}
}
My results.html
file = which is the pop-up:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="allVideos"><i>Loading...</i></div>
<script src="../jquery-1.9.1.min.js"></script>
<script src="../code/popup.js"></script>
</body>
</html>
My popup.js
file = the file that writes the HTML code in the "results.html" file:
(function () {
console.log("EntrĂ³");
init_code();
})();
/**
* Function that initializes the page.
*/
function init_code() {
try {
// Initial variables:
var html_code = "";
// Get all videos:
// Source: https://www.sitepoint.com/create-firefox-add-on/
browser.storage.sync.get(['all_videos'])
.then((result) => {
if (result.hasOwnProperty('all_videos') && result.all_videos) {
if (result.all_videos && result.all_videos.length) {
// Build initial HTML table code:
html_code += `<table id="myTable"><tr><th>Thumbnail</th><th>Title</th><th>Channel_ID</th></tr>`;
// Loop over the items and build the HTML with their data:
result.all_videos.forEach((item) => {
html_code += appendItem(item);
});
// Finish the HTML table code:
html_code += "</table>";
} else {
// Show: "no items available":
html_code = '<strong>No videos are stored on the localStorage.</strong>';
}
} else {
// Show: "no items available":
html_code = '<strong>No videos are stored on the localStorage.</strong>';
}
}, onErrorDetails);
console.log("Ok!");
// Show the results:
document.getElementById("allVideos").innerHTML = html_code;
} catch (ex) {
console.log("Error at the popup");
console.log("Error: " + ex.message);
console.log("Stack: " + ex.stack);
}
}
/**
* Function that builds the HTML to be added on the main HTML div.
* @param {object} item The item (i.e, the object that contains the video's data).
* @returns string
*/
function appendItem(item) {
return `<tr><img src='${item.Thumbnail}' alt='${item.Title}' /></tr><tr><span>${item.Title}</span></tr><tr><span>${item.Channel}</span></tr><tr><span>${item.Channel_ID}</span></tr>`;
}
/**
* Function that handles the error(s) - if any - when the info is obtained from the localStorage.
* @param {object} error_dt The object with the error details.
*/
function onErrorDetails(error_dt) {
console.log("Error!");
console.log(error_dt);
}
My goal is:
I want the add-on shows a pop-up dialog with the HTML I want to specify - in this case, a HTML
<table>
as shown in the example above.
My current issue is:
Despite all variations made in the manifest.json
file, the popup.js
code is not triggered at all.
Current result: Shows the "Loading..." text embed in the HTML file, when it should build the table
HTML.
I've read about the user interface and popups in the documentation; however, I followed step-by-step the different tutorial(s) I've found, but, I haven't found a reason about why this code is not running - no even errors or logs in the console.
Can anyone point me to the right path to achive this goal?
1 In the documentation - section "specifying a popup", the add-on uses a base HTML with a pre-defined HTML, but, I haven't found if this "base HTML" can be modified with javascript.
Ok, I finally figure it out.
The key parts are:
browser.storage.sync.set
and browser.storage.sync.get
for use the localStorage. I did follow this tutorial.manifest.json
and popup.html
files = the files that uses your resources. In my case, I didn't set the relative path to the .js file correctly = resulting in not being able to use javascript code at all..js
file that executes your code in your popup.html
file (in my case, the popup.js
file) must be added all (including functions) inside de $(document).ready(() => {
code block (or its equivalent)1.I share my manifest.json
file:
{
"manifest_version": 2,
"name": "Ejemplo",
"version": "1.0",
"description": "Inspeccionar elementos de youtube.com.",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/main/beastify",
"icons": {
"48": "icons/border-48.png"
},
"applications": {
"gecko": {
"id": "manhunter45a45@example.com"
}
},
"permissions": [
"tabs",
"activeTab",
"storage"
],
"browser_action": {
"default_icon": "icons/beasts-32.png",
"default_title": "Obtain YouTube Info",
"default_popup": "popup/results.html",
"browser_style": true
},
"content_scripts": [
{
"matches": [
"https://*.youtube.com/"
],
"js": [
"jquery-1.9.1.min.js",
"Ejemplo.js",
"/code/functions.js",
"/code/popup.js"
]
}
]
}
results.html
= my popup:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="../css/popup.css" rel="stylesheet" />
</head>
<body>
<table id="myTable">
<tr>
<th>Channel</th>
<th>No. of videos</th>
</tr>
</table>
<script src="../jquery-1.9.1.min.js"></script>
<script src="../code/popup.js"></script>
</body>
</html>
popup.js
= the file that creates the HTML and appends it to results.html
:
$(document).ready(() => {
// Source: https://www.sitepoint.com/create-firefox-add-on/
browser.storage.sync.get(['all_videos']).then((result) => {
// Loop over the items and build the HTML with their data:
result.all_videos.forEach((item) => {
appendItem(item);
});
}, onErrorDetails);
/**
* Function that builds the HTML to be added.
* @param {object} item The item (i.e, the object that contains the video's data).
* @returns string
*/
function appendItem(item) {
// Append the row(s) to the table:
// Source: https://www.enablegeek.com/tutorial/jquery-add-row-to-table/
$('#myTable tbody').append(`<tr>
<td>
<td><span>${item.channelName}</span></td>
<td><span>${item.qtyVideos}</span></td>
</tr>`);
}
/**
* Function that handles the error(s) - if any - when the info is obtained from the localStorage.
* @param {object} error_dt The object with the error details.
*/
function onErrorDetails(error_dt) {
console.log("Error!");
console.log(error_dt);
}
});
1 I suspect this is due to the webpage lifecycle; for some reason, I could not use document.getElementById("...")
- everytime I got undefined
, so, instead, I have to use JQuery for append the HTML in construction - i.e: $('#myTable tbody').append(<my_string_html>);
- see here how to append a row to a table using JQuery.