I am using a panel called by widget to take a snapshot of storage and display it in a table. BUt there appears to be some duplication on the markup being done.
Basically I have one storage item for testing purposes and a couple of settings like switches. Every time I click on the widget to open it the storage item gets duplicated on the page. I can understand that as the panel does not reload on show/hide.
The main issue is that I have a normal jQuery click event to send some data back to storage and this also seems to get duplicated. If I open and close the panel 6 times I get six events firing from one click.
This says to me that each reload is creating more listeners but I cannot find anything to tell me how to remove the listeners correctly.. See example
Content script
testPanel = require("sdk/panel").Panel({
contentURL: data.url("test.html"),
contentScriptFile: [data.url("test.js")],
onShow: function() {
testPanel.port.emit("Loaded")
testPanel.port.on("clicked", function(){
console.log('received click')
});
}
});
require("sdk/widget").Widget({
id: "my-widget",
label: "My Widget",
panel: testPanel,
content: "Click here"
});
test.js
var el = document.getElementsByTagName('a')[0];
el.addEventListener('click', function() {
console.log('clicked');
self.port.emit("clicked");
});
self.port.on("Loaded", function() {
$(".wrapper").append('<div>New element</div>');
});
Console Output
info: test_addon: Script loaded
info: test_addon: clicked
info: test_addon: received click
info: test_addon: clicked
info: test_addon: received click
info: test_addon: received click
info: test_addon: clicked
info: test_addon: received click
info: test_addon: received click
info: test_addon: received click
Anyone had similar issues?
Problem solved
Usage of removeListener()
is not 100% clear but by using a global function instead of an anonymous one you can remove the event listener onHide
. It will then create a new instance onShow
but the old one has been removed. Phew!
Content script
function showClick() {
console.log('received click')
}
testPanel = require("sdk/panel").Panel({
contentURL: data.url("test.html"),
contentScriptFile: [data.url("test.js")],
onShow: function() {
testPanel.port.emit("Loaded");
testPanel.port.on("clicked", showClick);
},
onHide: function() {
testPanel.port.removeListener('clicked', showClick);
}
});
I know you solved the problem but generally you don't want to create listeners in the onShow
method. I'd recommend you create your listener outside of the onShow
method and if you need to you can use the isShowing
property to check if the panel is open when you receive the event. Now you just have a single listener for the life of the panel.
function showClick() {
console.log('received click')
}
testPanel = require("sdk/panel").Panel({
contentURL: data.url("test.html"),
contentScriptFile: [data.url("test.js")],
onShow: function() {
testPanel.port.emit("Loaded");
},
onHide: function() {
}
});
testPanel.port.on("clicked", function() {
if (testPanel.isShowing) {
console.log('received click');
}
});