
de.larmic.butterfaces.component.renderkit.html_basic.action.CommandLinkRenderer Maven / Gradle / Ivy
package de.larmic.butterfaces.component.renderkit.html_basic.action;
import de.larmic.butterfaces.component.html.action.HtmlCommandLink;
import de.larmic.butterfaces.component.partrenderer.StringUtils;
import de.larmic.butterfaces.resolver.AjaxClientIdResolver;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIOutput;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
/**
* Created by larmic on 16.09.14.
*/
@FacesRenderer(componentFamily = HtmlCommandLink.COMPONENT_FAMILY, rendererType = HtmlCommandLink.RENDERER_TYPE)
public class CommandLinkRenderer extends com.sun.faces.renderkit.html_basic.CommandLinkRenderer {
private static final String WEB_XML_AJAX_PROCESSING_TEXT = "de.larmic.butterfaces.ajaxProcessingTextOnRequest";
/**
* Will be set in renderAsActive if f:ajax child with onevent attribute exists.
*/
private String onEventCallback = null;
@Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
this.onEventCallback = null;
super.encodeBegin(context, component);
}
@Override
protected boolean shouldWriteIdAttribute(UIComponent component) {
return true;
}
@Override
protected void writeCommonLinkAttributes(final ResponseWriter writer, final UIComponent component) throws IOException {
final HtmlCommandLink link = (HtmlCommandLink) component;
final String styleClass = (String) component.getAttributes().get("styleClass");
final StringBuilder generatedStyleClass = new StringBuilder(StringUtils.isEmpty(styleClass) ? "" : styleClass);
if (link.isDisabled()) {
generatedStyleClass.append(" disabled");
}
if (generatedStyleClass.length() > 0) {
writer.writeAttribute("class", generatedStyleClass.toString(), "styleClass");
}
}
@Override
public void decode(FacesContext context, UIComponent component) {
final ExternalContext external = context.getExternalContext();
final Map params = external.getRequestParameterMap();
final String resetValues = params.get("javax.faces.partial.resetValues");
final String render = params.get("javax.faces.partial.render");
if (StringUtils.isNotEmpty(resetValues) && StringUtils.isNotEmpty(render) && Boolean.valueOf(resetValues)) {
final String[] split = render.split(" ");
for (String clientId : split) {
final UIComponent renderComponent = context.getViewRoot().findComponent(clientId);
resetValues(renderComponent);
}
}
super.decode(context, component);
}
private void resetValues(final UIComponent component) {
if (component == null) {
return;
}
for (UIComponent child : component.getChildren()) {
resetValues(child);
}
if (component instanceof UIOutput) {
((UIOutput) component).resetValue();
} else if (component instanceof EditableValueHolder) {
((EditableValueHolder) component).resetValue();
}
}
@Override
public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
final HtmlCommandLink link = (HtmlCommandLink) component;
final ResponseWriter responseWriter = context.getResponseWriter();
if (link.isAjaxDisableLinkOnRequest()) {
responseWriter.startElement("script", component);
responseWriter.writeText("function " + getOnEventListenerName(component) + "(data) {", null);
if (StringUtils.isNotEmpty(onEventCallback)) {
responseWriter.writeText(" " + onEventCallback + "(data);", null);
}
final String processingText = createAjaxProcessingText(link);
final AjaxClientIdResolver ajaxClientIdResolver = new AjaxClientIdResolver(link);
final String jQueryIDSelector = link.isAjaxDisableRenderRegionsOnRequest()
? ajaxClientIdResolver.getjQueryRenderIDSelector() : "undefined";
responseWriter.writeText(" butter.link.disableOnClick(data, " +
link.isAjaxShowWaitingDotsOnRequest() + ",'" +
link.getValue() + "','" +
processingText + "'," +
link.isAjaxHideGlyphiconOnRequest() + ",'" +
jQueryIDSelector + "');", null);
responseWriter.writeText("}", null);
responseWriter.endElement("script");
}
super.encodeEnd(context, component);
}
private String createAjaxProcessingText(final HtmlCommandLink link) {
if (StringUtils.isNotEmpty(link.getAjaxProcessingTextOnRequest())) {
return link.getAjaxProcessingTextOnRequest();
}
final String ajaxProcessingTextByWebXml = FacesContext.getCurrentInstance().getExternalContext().getInitParameter(WEB_XML_AJAX_PROCESSING_TEXT);
return StringUtils.isEmpty(ajaxProcessingTextByWebXml) ? "Processing" : ajaxProcessingTextByWebXml;
}
@Override
protected void writeValue(final UIComponent component, final ResponseWriter writer) throws IOException {
final HtmlCommandLink commandLink = (HtmlCommandLink) component;
this.writeGlyphiconIfNecessary(commandLink, writer);
writer.startElement("span", component);
writer.writeAttribute("class", "butter-component-glyphicon-text", null);
super.writeValue(component, writer);
writer.endElement("span");
this.writeWaitingDotsIfNecessary(commandLink, writer);
}
@Override
protected void renderAsActive(FacesContext context, UIComponent component) throws IOException {
AjaxBehavior ajaxBehavior = null;
if (((HtmlCommandLink) component).isAjaxDisableLinkOnRequest()) {
final Map behaviors = (AbstractMap) ((ClientBehaviorHolder) component).getClientBehaviors();
final List actionBehaviours = (List) behaviors.get("action");
if (actionBehaviours != null && !actionBehaviours.isEmpty()) {
for (AjaxBehavior actionBehaviour : actionBehaviours) {
ajaxBehavior = actionBehaviour;
if (StringUtils.isNotEmpty(ajaxBehavior.getOnevent())) {
onEventCallback = ajaxBehavior.getOnevent();
}
ajaxBehavior.setOnevent(getOnEventListenerName(component));
}
}
}
super.renderAsActive(context, component);
// reset ajax behaviour because otherwise a render of this component will not be work correctly (wrong js
// callback is registered if onevent is set on f:ajax.
if (ajaxBehavior != null) {
ajaxBehavior.setOnevent(onEventCallback);
}
}
private String getOnEventListenerName(final UIComponent component) {
final char separatorChar = UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());
return "glyphiconLinkListener" + "_" + component.getClientId().replace(separatorChar + "", "_");
}
protected void writeWaitingDotsIfNecessary(final HtmlCommandLink commandLink,
final ResponseWriter writer) throws IOException {
if (commandLink.isAjaxDisableLinkOnRequest()) {
writer.startElement("span", commandLink);
writer.writeAttribute("class", "butter-component-glyphicon-processing", null);
writer.endElement("span");
}
}
protected void writeGlyphiconIfNecessary(final HtmlCommandLink commandLink,
final ResponseWriter writer) throws IOException {
final String glyphicon = commandLink.getGlyphicon();
if (glyphicon != null && !"".equals(glyphicon)) {
writer.startElement("span", commandLink);
writer.writeAttribute("class", "butter-component-glyphicon " + glyphicon, null);
writer.endElement("span");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy