Reputation: 809
I'm trying to make a firefox addon using their sdk, but I don't know how to make my js scripts comunicate. The goal is to make a panel with a form in witch there are 3 checkboxes that when selected can hide/show certain elements on the active tab.
Here are the scripts: main.js:
exports.main = function() {};
var data = require("sdk/self").data;
var panel1 = require("sdk/panel").Panel({
width: 215,
height: 160,
contentURL: data.url("panelDestroyer.html"),
contentScriptFile: [data.url("jquery.js"),data.url("panel.js")]
});
require("sdk/widget").Widget({
id: "open-form-btn",
label: "Clear",
contentURL: data.url("mozico.png"),
contentScriptFile: data.url("jquery.js"),
panel: panel1
});
var tabs = require("sdk/tabs");
var tabWorkers = {};
tabs.on("ready", function(tab) {
attachTabWorker(tab);
});
for each (var tab in tabs) {
attachTabWorker(tab);
}
function attachTabWorker(tab) {
// Attach and store
var tabWorker = tabWorkers[tab.id] = tab.attach({
contentScriptFile: [data.url("clear.js"),data.url("jquery.js")]
});
// Clean up
tabWorker.on("detach", function() {
if (getTabWorker(tab) === tabWorker) {
delete tabWorkers[tab.id];
}
});
}
function getTabWorker(tab) {
return tabWorkers[tab.id];
}
function getActiveTabWorker() {
return getTabWorker(tabs.activeTab);
}
panel1.port.on("show-tag",function(tag){
getActiveTabWorker().port.emit("show-tag", tag);
console.log("worker emited");
});
panel1.port.on("clear-tag",function(tag){
getActiveTabWorker().port.emit("clear-tag", tag);
console.log("worker emited");
})
;
painel.js:
$("#imgD").click(function() {
if ($(this).is(":checked")) {
self.port.emit("clear-tag","img");
console.log("panel emited");
} else {
self.port.emit("show-tag","img");
console.log("panel emited");
}
});
$("#aD").click(function() {
if ($(this).is(":checked")) {
self.port.emit("clear-tag","a");
console.log("panel emited");
} else {
self.port.emit("show-tag","a");
console.log("panel emited");
}
});
$("#iframeD").click(function() {
if ($(this).is(":checked")) {
self.port.emit("clear-tag","iframe");
console.log("panel emited");
} else {
self.port.emit("show-tag","iframe");
console.log("panel emited");
}
});
clear.js:
function tagHide (tag, hide) {
$(tag).each(function() {
if (hide === false) {
$(this).css({
"visibility": "visible"
});
} else {
$(this).css({
"visibility": "hidden"
});
}
});
}
self.port.on('show-tag', function(tag) {
tagHide(tag, false);
});
self.port.on('clear-tag', function(tag) {
tagHide(tag, true);
});
Why do I keep getting that self.port is not defined in painel.js ?
Upvotes: 4
Views: 2395
Reputation: 50
I was also experiencing the same problem, and then found this question on SO: self.port is undefined error [on mozilla add-on SDK 1.8]
The problem is in the HTML code, you must be calling the script in both the main.js and html. Removing it from the html, and declaring it directly in main.js will solve this error.
Upvotes: 1
Reputation: 20159
I believe the problem is that you're trying to attach a content script when the add-on is loaded.
let worker = require("sdk/tabs").activeTab.attach({
contentScriptFile: data.url("clear.js")
});
I think activeTab
may not be ready yet when your add-on is just loaded, which is usually when Firefox is starting. Perhaps the DOM is not fully loaded yet or the SDK could not properly initialize all components for the content script.
The SDK documentation states that you should wait until the ready
event before using content-related properties and methods. I assume attaching content scripts also falls in that category, so you probably need to rework that to something like:
let worker = null;
require("sdk/tabs").activeTab.on("ready", function(tab) {
worker = tab.attach({
contentScriptFile: data.url("clear.js")
});
});
This is still insufficient though, as the user may switch tabs. When you register the ready
listener on the original activeTab
, you won't be listening to the newly activated tab and no content scripts will be attached to that tab. You'll need to:
ready
event of all tabs;I quickly whipped up something which should do just that. You should be able to use getActiveTabWorker()
in your panel
port events to target the correct worker. It's still untested, so give it a try!
const tabs = require("sdk/tabs");
let tabWorkers = {};
tabs.on("ready", function(tab) {
attachTabWorker(tab);
});
for each (let tab in tabs) {
attachTabWorker(tab);
}
function attachTabWorker(tab) {
// Attach and store
let tabWorker = tabWorkers[tab.id] = tab.attach({
contentScriptFile: data.url("clear.js")
});
// Clean up
tabWorker.on("detach", function() {
if (getTabWorker(tab) === tabWorker) {
delete tabWorkers[tab.id];
}
});
}
function getTabWorker(tab) {
return tabWorkers[tab.id];
}
function getActiveTabWorker() {
return getTabWorker(tabs.activeTab);
}
EDIT: I have no idea how self.port
can be undefined, but I found some more errors you need to fix. Perhaps one of those is indirectly interfering with self
?
main.js
is listening for hide-tag
, whereas your panel emits clear-tag
. Use clear-tag
.tag
instead of {tag:tag}
.data.url("jquery.js")
to contentScriptFile
in attachTabWorker
.Upvotes: 5