高级用户界面元素及其操作Firefox 扩展一般使用 XUL 来创建用户界面。相对于 HTML 来说,XUL 提供了更加丰富的用户界面组件,同时也支持用 CSS 来定义 XUL 元素的外观样式。大部分简单 XUL 元素的使用比较好理解,下面主要介绍一些复杂的用户界面组件及其用法。
窗口一般的 Firefox 扩展都会打开一个新的窗口来展示界面。通常的做法是在用户点击菜单项或是工具栏上的按钮之后,弹出来一个新的窗口,与用户进行交互。通过 XUL 的 window 元素可以创建一个新的窗口,并在窗口中包含其它的 XUL 用户界面元素作为内容。通过 window.open() 方法就可以打开一个新的窗口。该方法的返回值是窗口对象的一个引用,可以用来查看窗口的属性和对其进行操作,比如通过其 document 属性就可以获取到窗口文档的 DOM 对象。
在扩展中经常会需要对窗口进行查询。这里可以用 nsIWindowMediator 服务。该服务可以用来根据窗口类型进行查询。nsIWindowMediator 服务是一个 组件。关于 XPCOM 组件的细节,会在下面的章节中介绍。 中给出了 nsIWindowMediator 的使用示例。
清单 1. 使用 nsIWindowMediator 查询窗口1
2
3
4
5
6
7
| var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var enumerator = wm.getEnumerator("navigator:browser");
while(enumerator.hasMoreElements()) {
var win = enumerator.getNext(); // 迭代器中的每个元素都是一个窗口对象
alert(win.document.title);
}
|
如 所示,navigator:browser 是 Firefox 中浏览网页的窗口的类型。nsIWindowMediator 服务的 getEnumerator() 方法可以得到一个用来遍历所有指定类型窗口的迭代器。nsIWindowMediator 的另一个方法 getMostRecentWindow() 可以用来获取到最近打开的指定类型的窗口。该方法通常用来检查某个窗口是否已经被打开了。一般的做法是在窗口的 windowtype 属性上设置一个自定义的窗口类型,然后就可以用 getMostRecentWindow() 方法来查询此类型的窗口是否已经被打开。 给出了一个在扩展中常用的方法。该方法首先判断某个窗口是否已经被打开,如果没有,就打开此窗口,否则就把焦点移到该窗口上。
清单 2. 打开窗口或把焦点移到已有窗口上1
2
3
4
5
6
7
8
9
10
| var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("dwSample-custom-window");
if (win) {
win.focus(); // 设置窗口为当前焦点
}
else {
window.open("chrome://dwSample/content/custom-window.xul",
"dwSample-test-custom-window","chrome,centerscreen");
}
|
如 所示,这里打开的窗口 custom-window.xul 中通过 windowtype 属性设置了自定义的窗口类型 dwSample-custom-window 。该类型是 getMostRecentWindow() 方法的参数。
在使用窗口时的另一个常见需求是向新打开的窗口传递数据,比如新窗口初始化时所需的数据。当一个新窗口被打开的时候,在新窗口中可以通过 window.opener 来访问打开它的窗口的 window 对象。如果新窗口总是以固定的方式被打开,也就是说 window.opener 的值是确定的话,可以通过 window.opener 来进行数据传递。如果 window.opener 属性的值不确定的话,可以使用 nsIWindowWatcher 服务在打开新窗口的时候传递数据,具体用法见 。
清单 3. 使用 nsIWindowWatcher 传递数据1
2
3
4
5
6
| var args = { name : "Alex" };
args.wrappedJSObject = args;
var watcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
watcher.openWindow(null, "chrome://dwSample/content/window.xul",
"dwSample-test-window","chrome,centerscreen", args);
|
如 所示,args 就是传递给新窗口的参数。在新窗口中,可以通过 window.arguments 来获取到参数的值。window.arguments[0].wrappedJSObject 的值就是传递过来的 args 对象。 |