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

Java tutorial

Introduction

Here is the source code for org.projectforge.web.wicket.autocompletion.PFAutoCompleteTextField.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.List;

import org.apache.commons.lang.ObjectUtils;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.util.string.StringValue;
import org.projectforge.web.wicket.WicketUtils;

public abstract class PFAutoCompleteTextField<T> extends TextField<T> {
    private static final long serialVersionUID = 3207038195316387588L;

    /** auto complete behavior attached to this textfield */
    private PFAutoCompleteBehavior<T> behavior;

    private AbstractDefaultAjaxBehavior deleteBehavior;

    private PFAutoCompleteSettings settings;

    protected boolean providesTooltip;

    private IAutoCompleteRenderer<String> renderer;

    private static final String CONTENT = "delete";

    /**
     * @param id
     * @param model
     */
    protected PFAutoCompleteTextField(final String id, final IModel<T> model) {
        this(id, model, PFAutoCompleteRenderer.INSTANCE, new PFAutoCompleteSettings());// , type, StringAutoCompleteRenderer.INSTANCE,
        // settings);
    }

    protected PFAutoCompleteTextField(final String id, final IModel<T> model,
            final IAutoCompleteRenderer<String> renderer, final PFAutoCompleteSettings settings) {
        super(id, model);
        this.renderer = renderer;
        this.settings = settings;
    }

    /**
     * @see org.apache.wicket.Component#onInitialize()
     */
    @Override
    protected void onInitialize() {
        super.onInitialize();
        behavior = new PFAutoCompleteBehavior<T>(renderer, settings) {
            private static final long serialVersionUID = 1L;

            @Override
            protected List<T> getChoices(final String input) {
                return PFAutoCompleteTextField.this.getChoices(input);
            }

            @Override
            protected List<T> getFavorites() {
                return PFAutoCompleteTextField.this.getFavorites();
            }

            @Override
            protected List<String> getRecentUserInputs() {
                return PFAutoCompleteTextField.this.getRecentUserInputs();
            }

            @Override
            protected String formatValue(final T value) {
                return PFAutoCompleteTextField.this.formatValue(value);
            }

            @Override
            protected String formatLabel(final T value) {
                return PFAutoCompleteTextField.this.formatLabel(value);
            }
        };
        add(behavior);
        deleteBehavior = new AbstractDefaultAjaxBehavior() {
            private static final long serialVersionUID = 3014042180471042845L;

            @Override
            protected void respond(final AjaxRequestTarget target) {
                // Gather query params ?...&content=kssel
                final StringValue contentValue = RequestCycle.get().getRequest().getQueryParameters()
                        .getParameterValue(CONTENT);
                if (contentValue != null) {
                    final String contentString = contentValue.toString();
                    if (getForm() instanceof AutoCompleteIgnoreForm) {
                        ((AutoCompleteIgnoreForm) getForm()).ignore(PFAutoCompleteTextField.this, contentString);
                    } // else { just ignore }
                }
            }
        };
        add(deleteBehavior);
    }

    @Override
    public void renderHead(final IHeaderResponse response) {
        super.renderHead(response);
        response.render(OnDomReadyHeaderItem.forScript(
                "$('#" + this.getMarkupId() + "').data('callback', '" + deleteBehavior.getCallbackUrl() + "');"));
    }

    @SuppressWarnings("serial")
    public PFAutoCompleteTextField<T> enableTooltips() {
        WicketUtils.addTooltip(this, new Model<String>() {
            @Override
            public String getObject() {
                return PFAutoCompleteTextField.this.getTooltip();
            }
        });
        return this;
    }

    /** {@inheritDoc} */
    @Override
    protected void onComponentTag(final ComponentTag tag) {
        super.onComponentTag(tag);
        // disable browser's autocomplete
        tag.put("autocomplete", "off");
    }

    /**
     * Override this callback method that for returning favorite entries to show, if the user double clicks the empty input field. These
     * objects will be passed to the renderer to generate output.
     * 
     * @see AutoCompleteBehavior#getChoices(String)
     * 
     * @return null, if no favorites to show.
     */
    protected List<T> getFavorites() {
        return null;
    }

    /**
     * Override this callback method that for returning recent user inputs to show, if the user double clicks the empty input field.
     * 
     * @return null means: don't show recent user inputs.
     */
    protected List<String> getRecentUserInputs() {
        return null;
    }

    /**
     * Uses ObjectUtils.toString(Object) as default.
     * @param value
     * @return
     */
    protected String formatValue(final T value) {
        return ObjectUtils.toString(value);
    }

    /**
     * Only used if labelValue is set to true.
     * @param value
     * @return The label to show in the drop down choice. If not overloaded null is returned.
     */
    protected String formatLabel(final T value) {
        return null;
    }

    /**
     * Overwrite this method if a title attribute for the input text field should be set. Don't forget to call {@link #enableTooltips()}.
     * @return Tool-tip of the object currently represented by the input field or null.
     */
    protected String getTooltip() {
        return null;
    }

    /**
     * Callback method that should return a list of all possible assist choice objects. These objects will be passed to the renderer to
     * generate output.
     * 
     * @see AutoCompleteBehavior#getChoices(String)
     * 
     * @param input current input
     * @return list of all possible choice objects
     */
    protected abstract List<T> getChoices(String input);

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withAutoFill(boolean)
     */
    public PFAutoCompleteTextField<T> withAutoFill(final boolean autoFill) {
        settings.withAutoFill(autoFill);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withAutoSubmit(boolean)
     */
    public PFAutoCompleteTextField<T> withAutoSubmit(final boolean autoSubmit) {
        settings.withAutoSubmit(autoSubmit);
        return this;
    }

    /**
     * @return the settings
     */
    public PFAutoCompleteSettings getSettings() {
        return settings;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withFocus(boolean)
     */
    public PFAutoCompleteTextField<T> withFocus(final boolean hasFocus) {
        settings.withFocus(hasFocus);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withCacheLength(int)
     */
    public PFAutoCompleteTextField<T> withCacheLength(final int cacheLength) {
        settings.withCacheLength(cacheLength);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withDelay(int)
     */
    public PFAutoCompleteTextField<T> withDelay(final int delay) {
        settings.withDelay(delay);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withMatchCase(boolean)
     */
    public PFAutoCompleteTextField<T> withMatchCase(final boolean matchCase) {
        settings.withMatchCase(matchCase);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withMatchContains(boolean)
     */
    public PFAutoCompleteTextField<T> withMatchContains(final boolean matchContains) {
        settings.withMatchContains(matchContains);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withMatchSubset(boolean)
     */
    public PFAutoCompleteTextField<T> withMatchSubset(final boolean matchSubset) {
        settings.withMatchSubset(matchSubset);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withMaxItemsToShow(int)
     */
    public PFAutoCompleteTextField<T> withMaxItemsToShow(final int maxItemsToShow) {
        settings.withMaxItemsToShow(maxItemsToShow);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withMinChars(int)
     */
    public PFAutoCompleteTextField<T> withMinChars(final int minChars) {
        settings.withMinChars(minChars);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withMustMatch(boolean)
     */
    public PFAutoCompleteTextField<T> withMustMatch(final boolean mustMatch) {
        settings.withMustMatch(mustMatch);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withScroll(boolean)
     */
    public PFAutoCompleteTextField<T> withScroll(final boolean scroll) {
        settings.withScroll(scroll);
        return this;
    }

    /**
     * Fluent.
     */
    public PFAutoCompleteTextField<T> withScrollHeight(final int scrollHeight) {
        settings.withScrollHeight(scrollHeight);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withSelectFirst(boolean)
     */
    public PFAutoCompleteTextField<T> withSelectFirst(final boolean selectFirst) {
        settings.withSelectFirst(selectFirst);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withSelectOnly(boolean)
     */
    public PFAutoCompleteTextField<T> withSelectOnly(final boolean selectOnly) {
        settings.withSelectOnly(selectOnly);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withWidth(int)
     */
    public PFAutoCompleteTextField<T> withWidth(final int width) {
        settings.withWidth(width);
        return this;
    }

    /**
     * Fluent.
     * @see PFAutoCompleteSettings#withLabelValue(boolean)
     */
    public PFAutoCompleteTextField<T> withLabelValue(final boolean labelValue) {
        settings.withLabelValue(labelValue);
        return this;
    }

    /**
     * Fluent.
     */
    public PFAutoCompleteTextField<T> withDeletableItem(final boolean deletableItem) {
        settings.setDeletableItem(deletableItem);
        return this;
    }
}