package com.google.gsoc.web.mixins;
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.CSSClassConstants;
import org.apache.tapestry5.ComponentEventCallback;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventConstants;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.OptionModel;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Events;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.corelib.components.Select;
import org.apache.tapestry5.corelib.data.BlankOption;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.apache.tapestry5.util.TextStreamResponse;
@Import(library = {"autocompleteselect.js"})
@Events(EventConstants.PROVIDE_COMPLETIONS)
public class AutoCompleteSelect {
@InjectContainer
private Select select;
private static final String PARAM_NAME = "t:input";
static final String EVENT_NAME = "autocomplete";
@Inject
@Path("${tapestry.spacer-image}")
private Asset spacerImage;
@Inject
private TypeCoercer coercer;
@Inject
private ComponentResources resources;
@Environmental
private JavaScriptSupport javaScriptSupport;
@SuppressWarnings("unchecked")
@Parameter
private ValueEncoder encoderComplete;
@Parameter(value = "auto", defaultPrefix = BindingConstants.LITERAL)
private BlankOption blankOptionComplete;
@Parameter(value = "1", defaultPrefix = BindingConstants.LITERAL)
private Integer minChars;
private SelectModel model;
protected void beginRender(MarkupWriter writer)
{
Link link = resources.createEventLink(EVENT_NAME);
String id = select.getClientId() + ":input" ;
String loaderId = select.getClientId() + ":loader";
writer.element("input",
"type", "text",
"id", id,
"autocomplete" , "off",
"class" , "t-selectcomplete-input"
);
writer.end();
writer.element("img",
"src", spacerImage.toClientURL(),
"class", "t-autoloader-icon " + CSSClassConstants.INVISIBLE,
"alt", "",
"id", loaderId);
writer.end();
writer.element("br");
writer.end();
javaScriptSupport.addScript("new Tapestry.DynamicSelect('%s', %s, %s, %s, %s)", select.getClientId(), 300, minChars, "'" + link.toAbsoluteURI() + "'", showBlankOption());
}
Object onAutocomplete(@RequestParameter(PARAM_NAME) String input)
{
ComponentEventCallback<SelectModel> callback = new ComponentEventCallback<SelectModel>()
{
public boolean handleResult(SelectModel result)
{
SelectModel matches = coercer.coerce(result, SelectModel.class);
model = matches;
return true;
}
};
resources.triggerEvent(EventConstants.PROVIDE_COMPLETIONS, new Object[] { input }, callback);
JSONArray vector = new JSONArray();
for(OptionModel optionModel : model.getOptions()) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", toClient(optionModel.getValue()));
jsonObject.put("description", optionModel.getLabel());
vector.put(jsonObject);
}
System.out.println(model);
return new TextStreamResponse("text/html", vector.toString());
}
private boolean showBlankOption()
{
switch (blankOptionComplete)
{
case ALWAYS:
return true;
case NEVER:
return false;
default:
return !select.isRequired();
}
}
@SuppressWarnings("unchecked")
String toClient(Object object) {
return encoderComplete.toClient(object);
}
}