Re: Searching in a list of values (menulist, textbox)

Michael Hofer <[email protected]>
Newsgroups gmane.comp.mozilla.devel.xpfe
Message-ID <[email protected]>
Am 07.02.12 22:57, schrieb Michael Hofer:
>>> Not exactly what I want. Any ideas how to access/store the id of the
>>> selected entry for later retrieval (while displaying the displayValue)?
>>> Is there a way to access the textbox from within the
>>> 'ProviderAutoCompleteResult' (nsIAutoCompleteResult) to attach something
>>> like a 'selectedId' attribute to it?
>>
>> I'm now trying to use the comment field of the autocomplete textbox for
>> my id property (accessible via textbox.controller.getCommentAt(index)).
> [...]
>> Any ideas on how to get the selected index?
>
> I finally found a way. There is an 'autocomplete-did-enter-text'
> notification which can be observed. Because this notification is sent
> before the popup closes (as opposed to the ontextentered event), the
> index of the selected element is still available in the observer. So the
> comment (or other fields) from the chosen entry can be retrieved via
>
> subject.controller.getCommentAt(subject.popup.selectedIndex)

Somebody asked me for a code example for this. Here it is:

XUL (Autocomplete Textbox):
--------------------------------------------------------------
<panel id="kunde_popup_autocomplete" type="autocomplete" 
noautofocus="true" />
<textbox id="kunde"
          type="autocomplete"
          autocompletepopup="kunde_popup_autocomplete"
          autocompletesearch="json-autocomplete"
          completedefaultindex="true" forcecomplete="true"
          enablehistory="true"
          showcommentcolumn="true"
          autocompletesearchparam='[]'"/>

- The separate panel set via the autocompletepopup attribute on the 
textbox is not strictly necessary. But without it I got popup display 
problems in some places. Place the panel separately from the textbox 
(like on the top level of the document) if you've got display problems.

- "json-autocomplete" is my custom autosearch component implemented 
basically like described on 
https://developer.mozilla.org/en/How_to_implement_custom_autocomplete_search_component#Basic_example_for_Gecko_2.0_and_up_%28Firefox_4_.2F_Thunderbird_3.3_.2F_SeaMonkey_2.1%29

- The autcocompletesearchparam on the textbox is set via script on init 
to a string containing json encoded data (with the data key containing 
an an array of hashes each having fields for displayValue, comment, 
id,...) -> See http://pastebin.com/emg0nzWc for an according 
startSearch-implementation (autocompletesearchparam is received as 
searchParam there). In that implementation getValueAt(index) 
(nsIAutoCompleteResult) would return
   this.results[index]['displayValue']
while getCommentAt(index) would return
   this.results[index]['comment']
(or ['id'] if you used the comment field for the id)


Observer (for receiving the index of the selected entry)
----------------------------------------------------------

function myObserver()
{
   this.register();
}
myObserver.prototype = {
   observe: function(subject, topic, data) {
     var id = subject.controller.getCommentAt(subject.popup.selectedIndex);
     alert( 'id of selected element (read from comment field): ' + id );
   },
   register: function() {
     var observerService = 
Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
     observerService.addObserver(this, "autocomplete-did-enter-text", 
false);
   },
   unregister: function() {
     var observerService = 
Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
     observerService.removeObserver(this, "autocomplete-did-enter-text");
   }
};

var testObserver = new myObserver();

This will be called after autocomplete was at work (but before the popup 
closes, so the selectedIndex is still available here). There are more 
undocumented notifications like this in 
toolkit/components/autocomplete/nsAutoCompleteController.cpp: 
'autocomplete-will-enter-text', 'autocomplete-will-revert-text', 
'autocomplete-did-revert-text'


Improvements
----------------------------------------------------------------

It's generally a good idea to have the xulrunner or firefox source code 
available for reference when working on these less documented features. 
Also: Don't mess around too much with internals when you are not in 
control of your xulrunner-environment (like when writing plugins).

1) To implement additional fields (like a getIdAt(index)-function in 
your nsiAutoCompleteResult) it seems to be necessary to also extend 
(implement your own?) nsIAutoCompleteController. Without that, all you 
have available from the controller is comment, image, label/value and style.
I didn't do that yet. Code examples anyone?


2) The default panel associated with the autocomplete textbox uses a 
tree with two columns (one for the value, one for the comment) for 
display. Using a richlistbox gives better formatting options + free 
search string highlighting in the result list (similar to awesomebar in 
firefox). But

<panel id="kunde_popup_autocomplete" type="autocomplete-richlistbox" />

(as described in the tutorial) doesn't work properly for me (xulrunner 
2.0), but

<panel style="-moz-binding: 
url(chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup)" 
id="kunde_popup_autocomplete" type="autocomplete" noautofocus="true" />

does (You'd better define a corresponding css class for that style).

To modify the structure of the individual richlistitems, you can extend 
the XBL:

XBL
----
<binding id="my-autocomplete-richlistitem" 
extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-richlistitem">
     <content>
       <!-- copy/modify the content from 
chrome://global/content/bindings/autocomplete.xml#autocomplete-richlistitem 
here -->
     </content>
</binding>

CSS
---
.autocomplete-richlistitem {
   -moz-binding: 
url('/path/to/my-autocomplete.xml#my-autocomplete-richlistitem');
}

For modifying the popup (which is creating the 
autocomplete-richlistitems) also extend 
chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup.

Hope this helps somebody.

regards,
Michael
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.