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:

Image:xpconnect_textfield.png

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

词条统计

浏览:108 次

字数:5279

最后编辑:7 年前

编辑次数:0 次

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文