我已按照MDN's document创建了一个切换按钮插件。
除了一个问题外,一切正常:
切换按钮的面板变为空白,并显示以下错误消息:
JavaScript错误:资源:///modules/WindowsPreviewPerTab.jsm,第406行:NS_ERR OR_FAILURE:组件返回失败代码:0x80004005(NS_ERROR_FAILURE)[nsIT askbarTabPreview.invalidate]
// ./lib/main.js
var { ToggleButton } = require("sdk/ui/button/toggle");
var panels = require("sdk/panel");
var self = require("sdk/self");
var buttonIndex = 0;
var lastKnownButtonIndex = 0;
var button = ToggleButton({
id: "button",
label: "my button",
icon: {
"16": "./icon-16.png"
},
onClick: handleChange,
});
var panel = panels.Panel({
contentURL: self.data.url("menu.html"),
onHide: handleHide
});
function handleChange(state) {
if (state.checked) {
panel.show({
position: button
});
}
}
function handleHide() {
button.state('window', {checked: false});
}
function assignButtonIndex() {
return (buttonIndex++).toString();
}
完整的插件位于:https://goo.gl/9N3jle
要重现:提取zip文件并$ cd testButton; cfx run
并按照上述步骤操作。
我真的希望有人可以帮助我。提前谢谢!
答案 0 :(得分:1)
这是一个错误;你没有做错任何事。这是Windows焦点事件和面板事件之间的竞争条件,它可以防止面板的隐藏事件以某种方式正确发出。
在正确修复问题之前,您可以尝试使用解决方法进行缓解。我在错误中添加了一些解释:https://bugzilla.mozilla.org/show_bug.cgi?id=1174425#c2但简而言之,您可以尝试添加setTimeout
以在显示面板时稍微延迟,以避免窗口焦点的竞争条件。类似的东西:
const { setTimeout } = require("sdk/timers");
/* ... your code here ... */
function handleChange(state) {
if (state.checked) {
setTimeout(() => panel.show({ position: button }), 100);
}
}
答案 1 :(得分:0)
我目前正在使用一种解决方法,每当用户按下工具栏按钮时,我就会动态创建一个新的Panel
。
它比100ms的解决方法更快,并且还处理用户在面板打开时完全关闭其中一个浏览器窗口的情况。 (在这种情况下,100ms解决方法失败,仍然显示一个空白面板。)
它的工作原理如下:
let myPanel = null;
const toolbarButton = ToggleButton({
...,
onChange: function (state) {
if (state.checked) {
createPanel();
}
}
});
function createPanel(){
// Prevent memory leaks
if(myPanel){
myPanel.destroy();
}
// Create a new instance of the panel
myPanel = Panel({
...,
onHide: function(){
// Destroy the panel instead of just hiding it.
myPanel.destroy();
}
});
// Display the panel immediately
myPanel.show();
}