SuggestBox and SuggestOracle

340 views
Skip to first unread message

maratkalibek

unread,
May 30, 2007, 7:28:22 PM5/30/07
to Google Web Toolkit
Hello,
I want to modify values (adding or removing entries) provided to
suggest box during runtime. It is OK for adding new values, but how
can we remove values from suggest oracle?

rusty

unread,
May 31, 2007, 5:54:27 AM5/31/07
to Google Web Toolkit
I assume you're talking about the MultiWordSuggestOracle? It's true
that it only has an add method, but you can also implement your own.
The easiest way would be to get the source for this class (from
gwt_user.jar) and just create your own that has a remove method as
well as an add one.

Michael Press

unread,
May 31, 2007, 12:37:03 PM5/31/07
to Google Web Toolkit
It turns out it's quite difficult to create your SuggestOracle
implementation. I want one like MultiWordSuggestOracle that only
matches the beginning of the suggest terms (so it matches a sql "text
%"), not the beginning of each word.

You can't just subclass MWSO, but it's declared final.

You cannot just copy (and repackage) MultiWordSuggestOracle and muck
with it, because it uses the PrefixTree class, which is package-scope
only. If you try to also copy PrefixTree to fix that, you've got to
change all the package nomenclature in the JSNI (and even after I
tried that I still got JavaScript exceptions and gave up.) I was
eventually able to make my own MWSO subclass but it required copying a
dozen source files just to change a few lines of code.

Has anyone found a reasonably simple way to create their own
SuggestOracle or make a specialization of the MWSO?

Thanks,
Michael

Michael Press

unread,
Jun 1, 2007, 3:55:33 PM6/1/07
to Google Web Toolkit
Ok, I'm answering my own question here - I decided to try to create my
own SuggestOracle entirely from scratch instead of messing with the
default and highly complex MultiWordSuggestOracle.

I implemented my StartsWithSuggestOracle to match items that start
with the typed value, case-insensitive. It was fairly
straightforward; the only tricky part was figuring out that the
matching results given to the Response is List<Suggestion> not
List<String>, and that I had to implement my own Suggestion. The full
class implementation is pasted below.

My comparison of the query to all of the choices is just dumb
iteration, but it's fast enough in hosted mode and on FF to suffice,
even with my large and complex list of possible choices (900 bacteria
names that are 50-80 characters long).

For Google, here are my suggestions for simplifying this process:
* There should be a default implementation of Suggest since it seems
likely that most Oracles will use the basic implementation
* A default method for formatting the display string would be useful
so we all don't have to write StringBuffers to chop up and format the
string. Using a CSS style by default instead of the hard-coded
"<strong>" tags would be preferable.
* As mentioned above, a remove() method on SuggestOracle would make
sense.

Michael


package org.jcvi.camera.web.gwt.common.client.ui.suggest;

import org.jcvi.camera.web.gwt.common.client.service.log.Logger;

import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.rpc.IsSerializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
* Implementation of GWT's SuggestOracle that returns matching items
if they start with the specified query string
* (case-insensitive)
*
* @author Michael Press
*/
public class StartsWithSuggestOracle extends SuggestOracle
{
private static Logger _logger =
Logger.getLogger("org.jcvi.camera.web.gwt.common.client.ui.suggest.StartsWithSuggestOracle");

ArrayList items = new ArrayList();

public StartsWithSuggestOracle()
{
}

/**
* Wrapper class that's used for each matching Suggestion
returned.
*/
public static class StartsWithSuggestion implements Suggestion,
IsSerializable
{
private String _value;
private String _displayString;

/**
* Constructor used by RPC.
*/
public StartsWithSuggestion() { }

/**
* Constructor for <code>StartsWithSuggestion</code>.
*/
public StartsWithSuggestion(String value, String
displayString)
{
_value = value;
_displayString = displayString;
}

public String getDisplayString()
{
return _displayString;
}

public Object getValue()
{
return _value;
}
}

/**
* Implementation of the sole abstract method in parent
SuggestOracle. Determines which strings match the
* query string, populates a Response (which contains a
List<StartsWithSuggestion>) and passes it to the supplied
* Callback
*/
public void requestSuggestions(Request request, Callback callback)
{
final List/*<StartsWithSuggestion*/ suggestions =
computeItemsFor(request.getQuery().toLowerCase(), request.getLimit());
Response response = new Response(suggestions);
callback.onSuggestionsReady(request, response);
}

/**
* Decides which strings match the supplied query; in this case,
if the string starts with the query (case-insensitive)
*/
private List computeItemsFor(String query, int limit)
{
ArrayList/*<StartsWithSuggestion>*/ matches = new ArrayList();
for (int i = 0; i < items.size() && matches.size() < limit; i+
+)
if (query.matches(((String) items.get(i)).substring(0,
query.length()).toLowerCase()))
matches.add(getFormattedSuggestion(query, (String)
items.get(i)));
_logger.debug("found " + matches.size() + " matches for query
" + query);
return matches;
}

/**
* Formats the display string that will be shown in the SuggestBox
popup
*/
private StartsWithSuggestion getFormattedSuggestion(String query,
String suggestion)
{
StringBuffer formattedSuggestion = new StringBuffer()
.append("<strong>")
.append(suggestion.substring(0, query.length()))
.append("</strong>")
.append(suggestion.substring(query.length()));
return new StartsWithSuggestion(suggestion,
formattedSuggestion.toString());
}

public void add(String suggestion)
{
items.add(suggestion);
}

public void addAll(Collection collection)
{
_logger.debug("added " + collection.size() + " items to
StartsWithSuggestOracle");
items.addAll(collection);
}

/**
* Specifies that the display string we're returning in the
StartsWithSuggestion is HTML
*/
public boolean isDisplayStringHTML() {
return true;

Reply all
Reply to author
Forward
0 new messages