Wednesday, January 25, 2012

Suggest using JQuery Autocomplete and Wicket

You know that cool Google feature called Suggest? When you type into search input box, it offers you some possible search queries. JQuery has a plugin for this, it is called JQuery Autocomplete. In this article I will show you how to make Suggest feature using JQuery and Wicket.


1. First we need to include JQuery framework and JQuery UI extension, so we add the following lines to our Wicket page:

@Override
public void renderHead(IHeaderResponse response) {
    super.renderHead(response);
       
    response.renderJavaScriptReference("http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");       
    response.renderJavaScriptReference("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js");        
    response.renderCSSReference("http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/themes/base/jquery-ui.css");
       
    response.renderJavaScriptReference("resource/suggest.js", "common");       
}

This method includes required javascript and styles to page header.

2. Then add input box into Wicket Template.

<div id="search">
    <form wicket:id="searchForm">
       Search <input type="text" wicket:id="searchText" />
       <input type="submit" value="Find" />
    </form>
</div>

3. Bind this input with Wicket Input Component

final TextField<String> searchText = new TextField<String>("searchText", Model.of("")); 

Form form = new StatelessForm("searchForm") {
    @Override
    protected void onSubmit() {
        PageParameters params = new PageParameters();
        params.add("search", searchText.getValue());
        setResponsePage(SearchPage.class, params);
    }
           
};

searchText.add(AttributeModifier.append("class", "search_autocomplete"));
form.add(searchText);

4. Then we need to create a page that would return suggested values for typed value:

Template:

<?xml version="1.0" encoding="UTF-8"?>
<suggestions>
   <suggestion wicket:id="suggestionList">
       <value wicket:id="value" />
   </suggestion>
</suggestions>



Suggest Class:

package web.pages;

import storage.DatabaseStorage;
import java.util.List;
import org.apache.wicket.Application;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;

/**
 * Suggestion - XML
 *
 * @author sergej.sizov
 */
public class SuggestionPage extends WebPage {

    public static final int SUGGESTION_COUNT = 10;
   
    @SpringBean
    private DatabaseStorage databaseStorage;
    private boolean stripTags;

    public SuggestionPage(PageParameters pageParameters) {
        setStatelessHint(true);
        stripTags = Application.get().getMarkupSettings().getStripWicketTags();

        final String search = pageParameters.get("search").toString();
        IModel<List<String>> allListModel = new LoadableDetachableModel<List<String>>() {
            @Override
            protected List<String> load() {
                return databaseStorage.getSuggestions(search, SUGGESTION_COUNT);
            }
        };

        ListView suggestListView = new ListView("suggestionList", allListModel) {
            @Override
            protected void populateItem(ListItem item) {
                item.add(new Label("value", item.getModel()));
            }
        };
        add(suggestListView);
    }
   
    @Override
    protected void configureResponse(WebResponse response) {
        super.configureResponse(response);
        response.setContentType("text/xml");
    }

    @Override
    protected void renderXmlDecl() {
        WebApplication.get().renderXmlDecl(this, true);
    }   
   
    @Override
    protected void onBeforeRender() {
        super.onBeforeRender();
        Application.get().getMarkupSettings().setStripWicketTags(true);
    }

    @Override
    protected void onAfterRender() {
        super.onAfterRender();       
        Application.get().getMarkupSettings().setStripWicketTags(stripTags);
    }
}


5. And finally javascript code suggestion.js:

$(document).ready(function(){
   
    $("input.search_autocomplete").autocomplete({
        minLength: 2,
        source: function( request, response ) {
           
            $.ajax( {
                url: "/suggest/" + request.term,
                dataType: "xml",
                cache: false,
                success: function(xml) {
                    var array = [];
                    $(xml).find('value').each(function() {
                        array.push($(this).text());
                    });
                    response(array);
                }
            });           
        }
    });
});

p.s. To learn more about JQuery Autocomplete visit http://jqueryui.com/demos/autocomplete/



No comments:

Post a Comment