org.richfaces.component.AbstractAutocomplete Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.richfaces.component;
import java.io.IOException;
import javax.el.MethodExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import org.richfaces.cdk.annotations.Attribute;
import org.richfaces.cdk.annotations.EventName;
import org.richfaces.cdk.annotations.JsfComponent;
import org.richfaces.cdk.annotations.JsfRenderer;
import org.richfaces.cdk.annotations.Signature;
import org.richfaces.cdk.annotations.Tag;
import org.richfaces.cdk.annotations.TagType;
import org.richfaces.context.ExtendedVisitContext;
import org.richfaces.context.ExtendedVisitContextMode;
import org.richfaces.renderkit.MetaComponentRenderer;
/**
* The <rich:autocomplete> component is an auto-completing input-box with built-in Ajax capabilities. It
* supports client-side suggestions, browser-like selection, and customization of the look and feel.
*
* @author Nick Belaevski
*/
@JsfComponent(tag = @Tag(type = TagType.Facelets, handler = "org.richfaces.view.facelets.AutocompleteHandler"),
renderer = @JsfRenderer(type = "org.richfaces.AutocompleteRenderer"),
attributes = {"focus-props.xml", "events-mouse-props.xml", "events-key-props.xml"})
public abstract class AbstractAutocomplete extends UIInput implements MetaComponentResolver, MetaComponentEncoder {
public static final String ITEMS_META_COMPONENT_ID = "items";
public static final String COMPONENT_TYPE = "org.richfaces.Autocomplete";
public static final String COMPONENT_FAMILY = UIInput.COMPONENT_FAMILY;
/**
* A collection of suggestions that will be resented to the user
*/
@Attribute()
public abstract Object getAutocompleteList();
/**
* A method which returns a list of suggestions according to a supplied prefix
*/
@Attribute(signature = @Signature(returnType = Object.class, parameters = { FacesContext.class, UIComponent.class,
String.class }))
public abstract MethodExpression getAutocompleteMethod();
public abstract void setAutocompleteMethod(MethodExpression expression);
/**
* Workaround for RF-11469
*/
@Attribute(hidden = true, signature = @Signature(returnType = Object.class, parameters = { String.class }))
public abstract MethodExpression getAutocompleteMethodWithOneParameter();
public abstract void setAutocompleteMethodWithOneParameter(MethodExpression expression);
/**
* A request-scope attribute via which the data object for the current row will be used when iterating
*/
@Attribute(literal = true)
public abstract String getVar();
// TODO nick - el-only?
/**
* A value to set in the target input element on a choice suggestion that isn't shown in the suggestion table.
* It can be used for descriptive output comments or suggestions. If not set, all text in the suggestion row is set as a value
*/
@Attribute(literal = false)
public abstract Object getFetchValue();
/**
* Minimal number of chars in input to activate suggestion popup
*/
@Attribute
public abstract int getMinChars();
/**
* Assigns one or more space-separated CSS class names to the selected suggestion entry
*/
@Attribute(defaultValue = "rf-au-itm-sel")
public abstract String getSelectedItemClass();
/**
* Assigns one or more space-separated CSS class names to the content of the popup suggestion element
*/
@Attribute()
public abstract String getPopupClass();
/**
* Assigns one or more space-separated CSS class names to the input element
*/
@Attribute()
public abstract String getInputClass();
/**
* Determine how the suggestion list is requested:
*
* - client
* - pre-loads data to the client and uses the input to filter the possible suggestions
* - ajax
* - fetches suggestions with every input change using Ajax requests
* - lazyClient
* -
* pre-loads data to the client and uses the input to filter the possible suggestions. The filtering does not start
* until the input length matches a minimum value. Set the minimum value with the minChars attribute.
*
* - cachedAjax
* -
* pre-loads data via Ajax requests when the input length matches a minimum value. Set the minimum value with the
* minChars attribute. All suggestions are handled on the client until the input prefix is changed, at which point
* a new request is made based on the new input prefix
*
*
* Default: cachedAjax
*/
@Attribute
public abstract AutocompleteMode getMode();
/**
*
* Type of the layout encoded using nested components should be defined using layout attribute.
* Possible values are:
*
*
* - list
* - suggestions wrapped to HTML unordered list
* - div
* - suggestions wrapped with just div element
* - table
* - suggestions are encoded as table rows, column definitions are required in this case
*
* Default: div
*/
@Attribute
public abstract String getLayout();
/**
* Allow a user to enter multiple values separated by specific characters. As the user types, a suggestion will
* present as normal. When they enter the specified token character, this begins a new suggestion process,
* and the component will then only use text entered after the token character for suggestions.
*
* Make sure that no character defined in tokens is part of any suggestion value. E.g. do not use space as a token
* if you expect to allow spaces in suggestion values.
*
* When tokens defined, they can be naturally separated by space character - input separated by tokens ', ' or ' ,'
* will be considered as it would be ',' token without any space.
*/
@Attribute
public abstract String getTokens();
/**
* Causes the combo-box to fill the text field box with a matching suggestion as the user types
*/
@Attribute(defaultValue = "true")
public abstract boolean isAutofill();
/**
* Boolean value indicating whether this component is disabled
* Default: false
*/
@Attribute
public abstract boolean isDisabled();
/**
* Boolean value indicating whether to display a button to expand the popup suggestion element
* Default: false
*/
@Attribute
public abstract boolean isShowButton();
/**
* Boolean value indicating whether the first suggestion item is selected as the user types
* Default: true
*/
@Attribute(defaultValue = "true")
public abstract boolean isSelectFirst();
/**
*
* A javascript function used to filter the result list returned from the ajax call to the server.
* This function should have two parameters; subString(current input value considering tokens)
* and value (currently iterated item value) and return boolean flag which means if the value satisfies the substring passed.
* The function will be called for every available suggestion in order to construct a new list of suggestions.
*
* Default: A javascript method called startsWith
*/
@Attribute
public abstract String getClientFilterFunction();
// ----------- selected core-props.xml
/**
* CSS style(s) to be applied when this component is rendered.
*/
@Attribute
public abstract String getStyle();
/**
* Space-separated list of CSS style class(es) to be applied when this element is rendered. This value must be
* passed through as the "class" attribute on generated markup.
*/
@Attribute
public abstract String getStyleClass();
// ----------- focus-props.xml
public abstract String getTabindex();
// ----------- Event Attributes
/**
* Javascript code executed when an item is selected
*/
@Attribute(events = @EventName("selectitem"))
public abstract String getOnselectitem();
/**
* Javascript code executed when this element loses focus and its value has been modified since gaining focus.
*/
@Attribute(events = @EventName(value = "change", defaultEvent = true))
public abstract String getOnchange();
// ----------- List events
/**
* Javascript code executed when a pointer button is clicked over the popup list element.
*/
@Attribute(events = @EventName("listclick"))
public abstract String getOnlistclick();
/**
* Javascript code executed when a pointer button is double clicked over this element.
*/
@Attribute(events = @EventName("listdblclick"))
public abstract String getOnlistdblclick();
/**
* Javascript code executed when a pointer button is pressed down over this element.
*/
@Attribute(events = @EventName("listmousedown"))
public abstract String getOnlistmousedown();
/**
* Javascript code executed when a pointer button is released over this element.
*/
@Attribute(events = @EventName("listmouseup"))
public abstract String getOnlistmouseup();
/**
* Javascript code executed when a pointer button is moved onto this element.
*/
@Attribute(events = @EventName("listmouseover"))
public abstract String getOnlistmouseover();
/**
* Javascript code executed when a pointer button is moved within this element.
*/
@Attribute(events = @EventName("listmousemove"))
public abstract String getOnlistmousemove();
/**
* Javascript code executed when a pointer button is moved away from this element.
*/
@Attribute(events = @EventName("listmouseout"))
public abstract String getOnlistmouseout();
/**
* Javascript code executed when a key is pressed and released over this element.
*/
@Attribute(events = @EventName("listkeypress"))
public abstract String getOnlistkeypress();
/**
* Javascript code executed when a key is pressed down over this element.
*/
@Attribute(events = @EventName("listkeydown"))
public abstract String getOnlistkeydown();
/**
* Javascript code executed when a key is released over this element.
*/
@Attribute(events = @EventName("listkeyup"))
public abstract String getOnlistkeyup();
// ----------- events-mouse-props.xml
@Attribute(events = @EventName("click"))
public abstract String getOnclick();
@Attribute(events = @EventName("dblclick"))
public abstract String getOndblclick();
@Attribute(events = @EventName("mousedown"))
public abstract String getOnmousedown();
@Attribute(events = @EventName("mouseup"))
public abstract String getOnmouseup();
@Attribute(events = @EventName("mouseover"))
public abstract String getOnmouseover();
@Attribute(events = @EventName("mousemove"))
public abstract String getOnmousemove();
@Attribute(events = @EventName("mouseout"))
public abstract String getOnmouseout();
// ----------- events-key-props.xml
@Attribute(events = @EventName("keypress"))
public abstract String getOnkeypress();
@Attribute(events = @EventName("keydown"))
public abstract String getOnkeydown();
@Attribute(events = @EventName("keyup"))
public abstract String getOnkeyup();
// ----------- focus-props.xml
@Attribute(events = @EventName("blur"))
public abstract String getOnblur();
@Attribute(events = @EventName("focus"))
public abstract String getOnfocus();
// ----------- selected ajax props
/**
* The client-side script method to be called before an ajax request.
*/
@Attribute(events = @EventName("begin"))
public abstract String getOnbegin();
/**
* The client-side script method to be called when an error has occurred during Ajax communications
*/
@Attribute(events = @EventName("error"))
public abstract String getOnerror();
/**
* The client-side script method to be called after the DOM is updated
*/
@Attribute(events = @EventName("complete"))
public abstract String getOncomplete();
/**
* The client-side script method to be called after the ajax response comes back, but before the DOM is updated
*/
@Attribute(events = @EventName("beforedomupdate"))
public abstract String getOnbeforedomupdate();
public String resolveClientId(FacesContext facesContext, UIComponent contextComponent, String metaComponentId) {
if (ITEMS_META_COMPONENT_ID.equals(metaComponentId)) {
return getClientId(facesContext) + MetaComponentResolver.META_COMPONENT_SEPARATOR_CHAR + metaComponentId;
}
return null;
}
public String substituteUnresolvedClientId(FacesContext facesContext, UIComponent contextComponent, String metaComponentId) {
return null;
}
@Override
public boolean visitTree(VisitContext context, VisitCallback callback) {
if (context instanceof ExtendedVisitContext) {
ExtendedVisitContext extendedVisitContext = (ExtendedVisitContext) context;
if (extendedVisitContext.getVisitMode() == ExtendedVisitContextMode.RENDER) {
VisitResult result = extendedVisitContext.invokeMetaComponentVisitCallback(this, callback,
ITEMS_META_COMPONENT_ID);
if (result == VisitResult.COMPLETE) {
return true;
} else if (result == VisitResult.REJECT) {
return false;
}
}
}
return super.visitTree(context, callback);
}
public void encodeMetaComponent(FacesContext context, String metaComponentId) throws IOException {
((MetaComponentRenderer) getRenderer(context)).encodeMetaComponent(context, this, metaComponentId);
}
}