org.projectforge.web.wicket.autocompletion.PFAutoCompleteBehavior.java Source code

Java tutorial

Introduction

Here is the source code for org.projectforge.web.wicket.autocompletion.PFAutoCompleteBehavior.java

Source

/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2013 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.web.wicket.autocompletion;

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

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.handler.TextRequestHandler;
import org.apache.wicket.util.string.Strings;
import org.projectforge.web.core.JsonBuilder;
import org.projectforge.web.wicket.WicketRenderHeadUtils;

public abstract class PFAutoCompleteBehavior<T> extends AbstractDefaultAjaxBehavior {
    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger
            .getLogger(PFAutoCompleteBehavior.class);
    private static final long serialVersionUID = -6532710378025987377L;

    protected PFAutoCompleteSettings settings;

    protected IAutoCompleteRenderer<String> renderer;

    public PFAutoCompleteBehavior(final IAutoCompleteRenderer<String> renderer,
            final PFAutoCompleteSettings settings) {
        this.renderer = renderer;
        this.settings = settings;
    }

    /**
     * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#renderHead(org.apache.wicket.Component,
     *      org.apache.wicket.markup.html.IHeaderResponse)
     */
    @Override
    public void renderHead(final Component component, final IHeaderResponse response) {
        super.renderHead(component, response);
        WicketRenderHeadUtils.renderMainJavaScriptIncludes(response);
        response.render(JavaScriptReferenceHeaderItem.forUrl("scripts/jquery.wicket-autocomplete.js"));
        renderAutocompleteHead(response);
    }

    /**
     * Render autocomplete init javascript and other head contributions
     * 
     * @param response
     */
    private void renderAutocompleteHead(final IHeaderResponse response) {
        final String id = getComponent().getMarkupId();
        String indicatorId = findIndicatorId();
        if (Strings.isEmpty(indicatorId)) {
            indicatorId = "null";
        } else {
            indicatorId = "'" + indicatorId + "'";
        }
        final StringBuffer buf = new StringBuffer();
        buf.append("var favorite" + id + " = ");
        final List<T> favorites = getFavorites();
        final MyJsonBuilder builder = new MyJsonBuilder();
        if (favorites != null) {
            buf.append(builder.append(favorites, false).getAsString());
        } else {
            buf.append(builder.append(getRecentUserInputs()).getAsString());
        }
        buf.append(";").append("var z = $(\"#").append(id).append("\");\n").append("z.autocomplete(\"")
                .append(getCallbackUrl()).append("\",{");
        boolean first = true;
        for (final String setting : getSettingsJS()) {
            if (first == true)
                first = false;
            else
                buf.append(", ");
            buf.append(setting);
        }
        if (first == true)
            first = false;
        else
            buf.append(", ");
        buf.append("favoriteEntries:favorite" + id);
        buf.append("});");
        if (settings.isHasFocus() == true) {
            buf.append("\nz.focus();");
        }
        final String initJS = buf.toString();
        // String initJS = String.format("new Wicket.AutoComplete('%s','%s',%s,%s);", id, getCallbackUrl(), constructSettingsJS(), indicatorId);
        response.render(OnDomReadyHeaderItem.forScript(initJS));
    }

    protected final List<String> getSettingsJS() {
        final List<String> result = new ArrayList<String>();
        addSetting(result, "matchContains", settings.isMatchContains());
        addSetting(result, "minChars", settings.getMinChars());
        addSetting(result, "delay", settings.getDelay());
        addSetting(result, "matchCase", settings.isMatchCase());
        addSetting(result, "matchSubset", settings.isMatchSubset());
        addSetting(result, "cacheLength", settings.getCacheLength());
        addSetting(result, "mustMatch", settings.isMustMatch());
        addSetting(result, "selectFirst", settings.isSelectFirst());
        addSetting(result, "selectOnly", settings.isSelectOnly());
        addSetting(result, "maxItemsToShow", settings.getMaxItemsToShow());
        addSetting(result, "autoFill", settings.isAutoFill());
        addSetting(result, "autoSubmit", settings.isAutoSubmit());
        addSetting(result, "scroll", settings.isScroll());
        addSetting(result, "scrollHeight", settings.getScrollHeight());
        addSetting(result, "width", settings.getWidth());
        addSetting(result, "deletableItem", settings.isDeletableItem());
        if (settings.isLabelValue() == true) {
            addSetting(result, "labelValue", settings.isLabelValue());
        }
        return result;
    }

    private final void addSetting(final List<String> result, final String name, final Boolean value) {
        if (value == null) {
            return;
        }
        result.add(name + ":" + ((value == true) ? "1" : "0"));
    }

    private final void addSetting(final List<String> result, final String name, final Integer value) {
        if (value == null) {
            return;
        }
        result.add(name + ":" + value);
    }

    /**
     * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#onBind()
     */
    @Override
    protected void onBind() {
        // add empty AbstractDefaultAjaxBehavior to the component, to force
        // rendering wicket-ajax.js reference if no other ajax behavior is on
        // page
        getComponent().add(new AbstractDefaultAjaxBehavior() {
            private static final long serialVersionUID = 1L;

            @Override
            protected void respond(final AjaxRequestTarget target) {
            }
        });
    }

    /**
     * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#respond(org.apache.wicket.ajax.AjaxRequestTarget)
     */
    @Override
    protected void respond(final AjaxRequestTarget target) {
        final RequestCycle requestCycle = RequestCycle.get();
        final org.apache.wicket.util.string.StringValue val = requestCycle.getRequest().getQueryParameters()
                .getParameterValue("q");
        onRequest(val != null ? val.toString() : null, requestCycle);
    }

    protected final void onRequest(final String val, final RequestCycle requestCycle) {
        // final PageParameters pageParameters = new PageParameters(requestCycle.getRequest().getParameterMap());
        final List<T> choices = getChoices(val);
        final MyJsonBuilder builder = new MyJsonBuilder();
        final String json = builder.append(choices).getAsString();
        requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler("application/json", "utf-8", json));

        /*
         * IRequestTarget target = new IRequestTarget() {
         * 
         * public void respond(RequestCycle requestCycle) {
         * 
         * WebResponse r = (WebResponse) requestCycle.getResponse(); // Determine encoding final String encoding =
         * Application.get().getRequestCycleSettings().getResponseRequestEncoding(); r.setCharacterEncoding(encoding);
         * r.setContentType("application/json"); // Make sure it is not cached by a r.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
         * r.setHeader("Cache-Control", "no-cache, must-revalidate"); r.setHeader("Pragma", "no-cache");
         * 
         * final List<T> choices = getChoices(val); renderer.renderHeader(r); renderer.render(JsonBuilder.buildRows(false, choices), r, val);
         * renderer.renderFooter(r); }
         * 
         * public void detach(RequestCycle requestCycle) { } }; requestCycle.setRequestTarget(target);
         */
    }

    /**
     * Callback method that should return an iterator over all possible choice objects. These objects will be passed to the renderer to
     * generate output. Usually it is enough to return an iterator over strings.
     * 
     * @param input current input
     * @return iterator over all possible choice objects
     */
    protected abstract List<T> getChoices(String input);

    /**
     * Callback method that should return a list of all possible default choice objects to show, if the user double clicks the empty input
     * field. These objects will be passed to the renderer to generate output. Usually it is enough to return an iterator over strings.
     */
    protected abstract List<T> getFavorites();

    /**
     * Callback method that should return a list of all recent user inputs in the text input field. They will be shown, if the user double
     * clicks the empty input field. These objects will be passed to the renderer to generate output. Usually it is enough to return an
     * iterator over strings. <br/>
     * Please note: Please, use only getFavorites() OR getRecentUserInputs()!
     */
    protected abstract List<String> getRecentUserInputs();

    /**
     * Used for formatting the values.
     */
    protected abstract String formatValue(T value);

    /**
     * Used for formatting the labels if labelValue is set to true.
     * @return null at default (if not overload).
     */
    protected String formatLabel(final T value) {
        return null;
    }

    private class MyJsonBuilder extends JsonBuilder {
        @SuppressWarnings("unchecked")
        @Override
        protected String formatValue(final Object obj) {
            if (obj instanceof String) {
                return obj.toString();
            } else {
                return PFAutoCompleteBehavior.this.formatValue((T) obj);
            }
        }

        @SuppressWarnings("unchecked")
        @Override
        protected Object transform(final Object obj) {
            if (settings.isLabelValue() == true) {
                final Object[] oa = new Object[2];
                if (obj instanceof String) {
                    oa[0] = obj;
                    oa[1] = obj;
                } else {
                    oa[0] = PFAutoCompleteBehavior.this.formatLabel((T) obj);
                    oa[1] = PFAutoCompleteBehavior.this.formatValue((T) obj);
                }
                return oa;
            } else {
                return obj;
            }
        }
    };
}