带有多个 windows 的空白 Firefox 插件面板页面
Blank Firefox addon panel page with multiple windows
我已经按照 MDN's document 创建了一个切换按钮插件。
除一个问题外一切正常:
- 打开第二个浏览器window(cmd+n 或 ctrl+n)并单击那里的切换按钮
- 点击原始浏览器上的切换按钮 window 而不关闭第二个 window 上的切换按钮
切换按钮的面板变为空白并显示以下错误消息:
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
并按照上述步骤操作。
我真的希望有人能帮我解决这个问题。提前致谢!
这是一个错误;你没有做错任何事。这是 windows' 焦点事件和面板事件之间的竞争条件,以某种方式阻止正确发出面板的隐藏事件。
您可以尝试通过解决方法来缓解问题,直到问题得到妥善解决。我在错误中添加了一些解释:https://bugzilla.mozilla.org/show_bug.cgi?id=1174425#c2 但简而言之,您可以尝试添加一个 setTimeout
以在显示面板时延迟一点,以避免与 window的重点。类似于:
const { setTimeout } = require("sdk/timers");
/* ... your code here ... */
function handleChange(state) {
if (state.checked) {
setTimeout(() => panel.show({ position: button }), 100);
}
}
我目前正在使用一种变通方法,每次用户按下工具栏按钮时我都会动态创建一个新的 Panel
。
它比 100 毫秒的解决方法更快,并且还可以处理用户在面板打开时完全关闭其中一个浏览器 windows 的情况。 (在这种情况下,100 毫秒的解决方法失败了,仍然显示空白面板。)
它是这样工作的:
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();
}
我已经按照 MDN's document 创建了一个切换按钮插件。
除一个问题外一切正常:
- 打开第二个浏览器window(cmd+n 或 ctrl+n)并单击那里的切换按钮
- 点击原始浏览器上的切换按钮 window 而不关闭第二个 window 上的切换按钮
切换按钮的面板变为空白并显示以下错误消息:
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
并按照上述步骤操作。
我真的希望有人能帮我解决这个问题。提前致谢!
这是一个错误;你没有做错任何事。这是 windows' 焦点事件和面板事件之间的竞争条件,以某种方式阻止正确发出面板的隐藏事件。
您可以尝试通过解决方法来缓解问题,直到问题得到妥善解决。我在错误中添加了一些解释:https://bugzilla.mozilla.org/show_bug.cgi?id=1174425#c2 但简而言之,您可以尝试添加一个 setTimeout
以在显示面板时延迟一点,以避免与 window的重点。类似于:
const { setTimeout } = require("sdk/timers");
/* ... your code here ... */
function handleChange(state) {
if (state.checked) {
setTimeout(() => panel.show({ position: button }), 100);
}
}
我目前正在使用一种变通方法,每次用户按下工具栏按钮时我都会动态创建一个新的 Panel
。
它比 100 毫秒的解决方法更快,并且还可以处理用户在面板打开时完全关闭其中一个浏览器 windows 的情况。 (在这种情况下,100 毫秒的解决方法失败了,仍然显示空白面板。)
它是这样工作的:
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();
}