Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@
<link>https://docs.oracle.com/en/java/javase/17/docs/api/</link>
<link>https://nightlies.apache.org/wicket/apidocs/11.x</link>
<link>https://docs.spring.io/spring-framework/docs/6.0.x/javadoc-api</link>
<link>https://logback.qos.ch/apidocs</link>
<link>https://javadoc.io/doc/ch.qos.logback/logback-classic/1.5.18</link>
<link>https://www.slf4j.org/apidocs</link>
</links>
<skip>${javadoc.disabled}</skip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public JQueryAjaxBehavior(IJQueryAjaxAware source)
* Constructor
*
* @param source {@link Behavior} to which the event - returned by {@link #newEvent()} - will be broadcasted.
* @param duration {@link Duration}. If different than {@link Duration#NONE}, an {@link ThrottlingSettings} will be added with the specified {@link Duration}.
* @param duration {@link Duration}. If different than {@link Duration#ZERO}, an {@link ThrottlingSettings} will be added with the specified {@link Duration}.
*/
public JQueryAjaxBehavior(IJQueryAjaxAware source, Duration duration)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public static boolean isEmpty(List<StringValue> list)
/**
* Converts a {@link StringValue} to a list of {@code String}
*
* @param value the {@link StringValue}
* @param values the {@link StringValue}
* @return a list of {@code String}
*/
public static List<String> toStringList(StringValue values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
*/
package org.wicketstuff.jquery.ui.form.autocomplete;

import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.lang.Args;
import org.danekja.java.util.function.serializable.SerializableSupplier;
import org.wicketstuff.jquery.core.IJQueryWidget;
import org.wicketstuff.jquery.core.JQueryBehavior;
import org.wicketstuff.jquery.core.renderer.ITextRenderer;
Expand All @@ -40,7 +41,7 @@
* @author Sebastien Briquet - sebfz1
* @author reiern70
*/
public abstract class AbstractAutoCompleteTextField<T> extends TextField<T> implements IJQueryWidget, IAutoCompleteListener // NOSONAR
public abstract class AbstractAutoCompleteTextField<T> extends TextField<T> implements IJQueryWidget, IAutoCompleteListener<T> // NOSONAR
{
private static final long serialVersionUID = 1L;

Expand All @@ -51,6 +52,7 @@ public abstract class AbstractAutoCompleteTextField<T> extends TextField<T> impl

private final ITextRenderer<? super T> renderer;
private final IConverter<T> converter;
private final IElementSelectionStrategy<T> elementSelectionStrategy;

private final IJQueryTemplate template;
private JQueryAbstractTemplateBehavior templateBehavior = null;
Expand Down Expand Up @@ -108,6 +110,7 @@ public AbstractAutoCompleteTextField(String id, ITextRenderer<? super T> rendere
this.renderer = renderer;
this.template = this.newTemplate();
this.converter = this.newConverter();
this.elementSelectionStrategy = this.newElementSelectionStrategy();
}

/**
Expand Down Expand Up @@ -145,7 +148,8 @@ public AbstractAutoCompleteTextField(String id, IModel<T> model, ITextRenderer<?
this(id, model, renderer, null);
}

/**

/**
* Constructor
*
* @param id the markup id
Expand All @@ -160,6 +164,7 @@ public AbstractAutoCompleteTextField(String id, IModel<T> model, ITextRenderer<?
this.renderer = renderer;
this.template = this.newTemplate();
this.converter = this.newConverter();
this.elementSelectionStrategy = this.newElementSelectionStrategy();
}

// Methods //
Expand Down Expand Up @@ -243,6 +248,16 @@ public ITextRenderer<? super T> getRenderer()
return this.renderer;
}

/**
* Gets the {@link IElementSelectionStrategy} used to identify and resolve selected choices.
*
* @return the selection strategy, never {@code null}
*/
public IElementSelectionStrategy<T> getElementSelectionStrategy()
{
return this.elementSelectionStrategy;
}

// Events //

@Override
Expand Down Expand Up @@ -292,17 +307,14 @@ protected void onComponentTag(final ComponentTag tag)
tag.put("autocomplete", "off"); // disable browser's autocomplete
}

@Override
public final void onSelect(AjaxRequestTarget target, int index)
{
if (-1 < index && index < this.choices.getObject().size())
{
T choice = this.choices.getObject().get(index);

this.setModelObject(choice);
this.onSelected(target);
}
}
@Override
public void onSelect(AjaxRequestTarget target, T choice,String identifier) {
if (choice != null) {
LOG.error("Cannot select choice with ID: {}", identifier);
}
this.setModelObject(choice);
this.onSelected(target);
}

/**
* Triggered when the user selects an item from results that matched its input
Expand All @@ -318,7 +330,13 @@ protected void onSelected(AjaxRequestTarget target)
@Override
public JQueryBehavior newWidgetBehavior(String selector)
{
return new AutoCompleteBehavior(selector, this) { // NOSONAR
return new AutoCompleteBehavior<T>(selector, this, new SerializableSupplier<List<T>>() {

@Override
public List<T> get() {
return choices != null ? choices.getObject() : Collections.emptyList();
}
}) { // NOSONAR

private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -394,18 +412,34 @@ public String convertToString(T value, Locale locale)
};
}

/**
* Gets a new {@link IElementSelectionStrategy}. Index-based selection is used by default.
*
* @return the selection strategy
*/
protected IElementSelectionStrategy<T> newElementSelectionStrategy()
{
return IndexBasedElementSelectionStrategy.get();
}

/**
* Gets a new {@link AutoCompleteChoiceModelBehavior}
*
* @return the {@link AutoCompleteChoiceModelBehavior}
*/
private AutoCompleteChoiceModelBehavior<T> newChoiceModelBehavior()
{
return new AutoCompleteChoiceModelBehavior<T>(this.renderer, this.template) { // NOSONAR

return new AutoCompleteChoiceModelBehavior<T>(this.renderer, this.template) // NOSONAR
{
private static final long serialVersionUID = 1L;
private static final String TERM = "term";

@Override
protected IElementSelectionStrategy<T> getElementSelectionStrategy()
{
return AbstractAutoCompleteTextField.this.getElementSelectionStrategy();
}

@Override
public List<T> getChoices()
{
Expand All @@ -415,4 +449,34 @@ public List<T> getChoices()
}
};
}

/**
* Gets the {@link AutoCompleteChoiceModelBehavior} that serves the choices to the widget
*
* @return the {@link AutoCompleteChoiceModelBehavior}, or {@code null} if the component has not been initialized yet
*/
public final AutoCompleteChoiceModelBehavior<T> getChoiceModelBehavior()
{
return this.choiceModelBehavior;
}

/**
* Gets the cached choices of the last query, used to resolve the user selected object
*
* @return the {@link IModel} of choices, or {@code null} if no query has been performed yet
*/
public final IModel<List<T>> getChoices()
{
return this.choices;
}

/**
* Gets the {@link JQueryAbstractTemplateBehavior} supplied by {@link #newTemplate()}
*
* @return the {@link JQueryAbstractTemplateBehavior}, or {@code null} if there is no template
*/
public final JQueryAbstractTemplateBehavior getTemplateBehavior()
{
return this.templateBehavior;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
*/
package org.wicketstuff.jquery.ui.form.autocomplete;

import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.CallbackParameter;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.lang.Args;
import org.danekja.java.util.function.serializable.SerializableSupplier;
import org.wicketstuff.jquery.core.JQueryEvent;
import org.wicketstuff.jquery.core.Options;
import org.wicketstuff.jquery.core.ajax.IJQueryAjaxAware;
Expand All @@ -32,40 +36,45 @@
*
* @author Sebastien Briquet - sebfz1
*/
public abstract class AutoCompleteBehavior extends JQueryUIBehavior implements IJQueryAjaxAware
public abstract class AutoCompleteBehavior<T> extends JQueryUIBehavior implements IJQueryAjaxAware
{
private static final long serialVersionUID = 1L;
public static final String METHOD = "autocomplete";

/** event listener */
private final IAutoCompleteListener listener;
private final IAutoCompleteListener<T> listener;

/** the model producing values */

private final SerializableSupplier<List<T>> supplier;

private JQueryAjaxBehavior onSelectAjaxBehavior = null;

/**
* Constructor
*
* @param selector the html selector (ie: "#myId")
* @param selector the HTML selector (ie: "#myId")
* @param listener the {@link IAutoCompleteListener}
*/
public AutoCompleteBehavior(String selector, IAutoCompleteListener listener)
public AutoCompleteBehavior(String selector, IAutoCompleteListener<T> listener, SerializableSupplier<List<T>> supplier)
{
this(selector, new Options(), listener);
this(selector, new Options(), listener, supplier);
}

/**
* Constructor
*
* @param selector the html selector (ie: "#myId")
* @param selector the HTML selector (ie: "#myId")
* @param options the {@link Options}
* @param listener the {@link IAutoCompleteListener}
*/
public AutoCompleteBehavior(String selector, Options options, IAutoCompleteListener listener)
public AutoCompleteBehavior(String selector, Options options, IAutoCompleteListener<T> listener, SerializableSupplier<List<T>> supplier)
{
super(selector, METHOD, options);

this.listener = Args.notNull(listener, "listener");
}
this.supplier = supplier;
}

// Methods //

Expand Down Expand Up @@ -108,16 +117,16 @@ public void onConfigure(Component component)
@Override
public void onAjax(AjaxRequestTarget target, JQueryEvent event)
{
if (event instanceof SelectEvent)
if (event instanceof SelectEvent selectEvent)
{
this.listener.onSelect(target, ((SelectEvent) event).getIndex());
this.listener.onSelect(target, listener.getElementSelectionStrategy().findChoice(supplier.get(), selectEvent.getIdentifier()), selectEvent.getIdentifier());
}
}

// Factories //

/**
* Gets a new {@link JQueryAjaxBehavior} that will be wired to the 'select' event
* Gets a new {@link JQueryAjaxBehavior} that will be wired to the 'select' eventta
*
* @param source the {@link IJQueryAjaxAware}
* @return a new {@code OnSelectAjaxBehavior} by default
Expand All @@ -127,7 +136,7 @@ protected JQueryAjaxBehavior newOnSelectAjaxBehavior(IJQueryAjaxAware source)
return new OnSelectAjaxBehavior(source);
}

// Ajax classes //
// Ajax classes //,

/**
* Provides a {@link JQueryAjaxBehavior} that aims to be wired to the 'select' event
Expand Down Expand Up @@ -163,16 +172,31 @@ protected JQueryEvent newEvent()
*/
protected static class SelectEvent extends JQueryEvent
{
private final int index;
private final String identifier;

public SelectEvent()
{
this.index = RequestCycleUtils.getQueryParameterValue("index").toInt(0);
this.identifier = RequestCycleUtils.getQueryParameterValue("index").toString();
}

public int getIndex()
/**
* Gets the selected item identifier (JSON {@code id}). For the default index strategy this is the list index.
*
* @return the identifier
*/
public String getIdentifier()
{
return this.index;
return this.identifier;
}
}

/**
* Gets the {@link JQueryAjaxBehavior} wired to the 'select' event
*
* @return the {@code OnSelectAjaxBehavior}, or {@code null} if the behavior has not been bound yet
*/
public final JQueryAjaxBehavior getOnSelectAjaxBehavior()
{
return this.onSelectAjaxBehavior;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* @param <T> the model object type
* @author Sebastien Briquet - sebfz1
*/
abstract class AutoCompleteChoiceModelBehavior<T> extends ChoiceModelBehavior<T>
public abstract class AutoCompleteChoiceModelBehavior<T> extends ChoiceModelBehavior<T>
{
private static final long serialVersionUID = 1L;

Expand All @@ -47,6 +47,16 @@ public AutoCompleteChoiceModelBehavior(ITextRenderer<? super T> renderer, IJQuer
super(renderer, template);
}

/**
* Gets the {@link IElementSelectionStrategy}. Index-based selection is used by default.
*
* @return the selection strategy
*/
protected IElementSelectionStrategy<T> getElementSelectionStrategy()
{
return IndexBasedElementSelectionStrategy.get();
}

@Override
protected String getResponse(IRequestParameters parameters)
{
Expand All @@ -61,7 +71,8 @@ protected String getResponse(IRequestParameters parameters)

// ITextRenderer //
final JSONObject object = this.renderer.render(choice);
object.put("id", Integer.toString(index)); /* 'id' is a reserved word */
String identifier = this.getElementSelectionStrategy().getIdentifier(choice, index);
object.put("id", identifier != null ? identifier : Integer.toString(index)); /* 'id' is a reserved word */
object.put("value", this.renderer.getText(choice)); /* 'value' is a reserved word */

// Additional properties (like template properties) //
Expand Down
Loading
Loading