Fun With XBL and XPConnect 编辑
Introduction
This article describes an application of XBL in which a simple XPCOM interface is made accessible to a XUL widget. The interface definition feature of XBL is used to define an interface through XPConnect to a C++ object that does auto completion. Once the regular XUL textfield widget is bound to this interface, it calls the auto complete function of the object using regular JavaScript. The basic model of interaction is as follows:
Binding to the XPCOM Object
The widget holds onto an XPCOM object that is the auto complete engine that will perform our auto complete lookups.
<binding name="autocomplete" extends="xul:box"> <content> <xul:textfield class="addressingWidget"/> <xul:menupopup/> </content> <implementation> <property name="autoCompleteSession"> <![CDATA[ Components.classes['component://netscape/messenger/autocomplete&type=addrbook']. getService(Components.interfaces.nsIAutoCompleteSession); ]]> </property>
So we've defined a property on the widget called autoCompleteSession
. The initial value of this property evaluates to an xp-connect object. Now accesses to autoCompleteSession
will return the xp-connect object.
Exposing the XPCOM Interfaces
One somewhat nasty trick you need to do is to manually expose the interfaces of the XPCOM object that you want your widget to support. All you have to do is specifically defining a method on the XBL widget which forwards the method call to the XPCOM object.
<method name="autoComplete"> <argument name="aSearchString"/> <argument name="resultListener"/> <body> <![CDATA[ return this.autoCompleteSession.autoComplete(null, anonymousContent[0], aSearchString, this.autoCompleteListener); ]]> </body> </method>
You can see that the body of the method is just getting the auto complete session object and calling the auto complete method on it.
Implementing a Widget Interface
The next thing I needed to do was to implement an interface on the widget which I could then pass into the auto complete session. I wanted the auto complete session to call back into the widget with search results. I could apply a trick similar to what I did for the XPCOM object:
<property name="autoCompleteListener"> <![CDATA[ ({ onAutoCompleteResult: function(aItem, aOriginalString, aMatch) { if ( aItem ) { anonymousContent[0].value = aMatch; } } }) ]]> </property>
As long as the JS for the value of autoCompleteListener
evaluates to an object (and wrapping the expression with a set of parens like I did, does this), then the value of autoCompleteListener
is an object that implements my interface.
Now I can pass the result of autoCompleteListener
into methods that require an auto complete listener (like my auto complete session object).
Creating the Event Handler
The last part is the easy part. I wanted a handler that would kick off the auto complete search. The handler calls the auto complete method we've exposed on the widget which in turn forwards the call to the XPCOM object, passing in our implementation of nsIAutoCompleteListener
.
<handlers> <handler type="keypress" keycode="vk_return" value="autoComplete(anonymousContent[0].value, this.autoCompleteListener);"/> </handlers> </implementation> </binding>
Original Document Information
- Author(s): Scott MacGregor
- Last Updated Date: April 13, 2000
- Copyright Information: Copyright (C) Scott MacGregor
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论