org.richfaces.renderkit.html.TooltipRenderer Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright ${year}, 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.renderkit.html;
import static org.richfaces.renderkit.HtmlConstants.CLASS_ATTRIBUTE;
import static org.richfaces.renderkit.HtmlConstants.ID_ATTRIBUTE;
import static org.richfaces.renderkit.RenderKitUtils.renderPassThroughAttributes;
import static org.richfaces.renderkit.html.TogglePanelRenderer.addEventOption;
import static org.richfaces.renderkit.html.TogglePanelRenderer.getAjaxOptions;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialResponseWriter;
import javax.faces.context.ResponseWriter;
import org.ajax4jsf.javascript.JSObject;
import org.richfaces.TooltipMode;
import org.richfaces.application.ServiceTracker;
import org.richfaces.cdk.annotations.JsfRenderer;
import org.richfaces.component.AbstractTooltip;
import org.richfaces.component.Positioning;
import org.richfaces.javascript.JavaScriptService;
import org.richfaces.renderkit.HtmlConstants;
import org.richfaces.renderkit.MetaComponentRenderer;
import org.richfaces.renderkit.RenderKitUtils;
import org.richfaces.renderkit.util.RendererUtils;
/**
* @author amarkhel
* @since 2010-10-24
*/
@ResourceDependencies({ @ResourceDependency(library = "javax.faces", name = "jsf.js"),
@ResourceDependency(name = "jquery.js"),
@ResourceDependency(name = "richfaces.js"),
@ResourceDependency(library = "org.richfaces", name = "richfaces-queue.reslib"),
@ResourceDependency(name = "richfaces-base-component.js"),
@ResourceDependency(name = "jquery.position.js"), @ResourceDependency(name = "richfaces-event.js"),
@ResourceDependency(library = "org.richfaces", name = "popup.js"),
@ResourceDependency(library = "org.richfaces", name = "tooltip.js"),
@ResourceDependency(library = "org.richfaces", name = "tooltip.ecss") })
@JsfRenderer(type = "org.richfaces.TooltipRenderer", family = AbstractTooltip.COMPONENT_FAMILY)
public class TooltipRenderer extends DivPanelRenderer implements MetaComponentRenderer {
public static final String HIDE = "hide";
public static final String SHOW = "show";
public static final String BEFORE_HIDE = "beforehide";
public static final String BEFORE_SHOW = "beforeshow";
private static final int DEFAULT_ZINDEX_VALUE = 1000;
private static final RendererUtils RENDERER_UTILS = RendererUtils.getInstance();
@Override
protected void doDecode(FacesContext context, UIComponent component) {
AbstractTooltip tooltip = (AbstractTooltip) component;
Map requestMap = context.getExternalContext().getRequestParameterMap();
String compClientId = component.getClientId(context);
String clientId = requestMap.get(compClientId);
if (clientId != null && clientId.equals(compClientId)) {
context.getPartialViewContext().getRenderIds().add(tooltip.getContentClientId(context));
// TODO nick - this should be done on encode, not on decode
addOnCompleteParam(context, tooltip.getClientId(context));
context.renderResponse();
}
}
@Override
protected void doEncodeBegin(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
AbstractTooltip tooltip = (AbstractTooltip) component;
writer.startElement(getMarkupElement(tooltip), component);
writer.writeAttribute(ID_ATTRIBUTE, component.getClientId(context), "clientId");
writer.writeAttribute(HtmlConstants.STYLE_ATTRIBUTE, "display: none;", null);
writer.startElement(getMarkupElement(tooltip), component);
writer.writeAttribute(ID_ATTRIBUTE, component.getClientId(context) + ":wrp", null);
writer.writeAttribute(CLASS_ATTRIBUTE, getStyleClass(component), null);
int zindex = tooltip.getZindex();
if (zindex == Integer.MIN_VALUE) {
zindex = DEFAULT_ZINDEX_VALUE;
}
String style = concatStyles("z-index:" + zindex, getStyle(component));
if (style != null && style.trim().length() > 0) {
writer.writeAttribute(HtmlConstants.STYLE_ATTRIBUTE, style, null);
}
renderPassThroughAttributes(context, component, getPassThroughAttributes());
writer.startElement(getMarkupElement(tooltip), component);
writer.writeAttribute(ID_ATTRIBUTE, component.getClientId(context) + ":cntr", null);
writer.writeAttribute(CLASS_ATTRIBUTE, "rf-tt-cntr", null);
if (tooltip.getMode() == TooltipMode.ajax) {
encodeLoading(writer, context, tooltip);
}
encodeContentBegin(writer, context, tooltip);
}
private void encodeContentBegin(ResponseWriter writer, FacesContext context, AbstractTooltip tooltip) throws IOException {
writer.startElement(getMarkupElement(tooltip), tooltip);
writer.writeAttribute(ID_ATTRIBUTE, tooltip.getClientId(context) + ":content", null);
writer.writeAttribute(CLASS_ATTRIBUTE, "rf-tt-cnt", null);
if (tooltip.getChildCount() == 0) {
writer.write(tooltip.getValue().toString());
}
}
private void encodeLoading(ResponseWriter writer, FacesContext context, AbstractTooltip tooltip) throws IOException {
writer.startElement(getMarkupElement(tooltip), tooltip);
writer.writeAttribute(ID_ATTRIBUTE, tooltip.getClientId(context) + ":loading", null);
writer.writeAttribute(CLASS_ATTRIBUTE, "rf-tt-loading", null);
UIComponent loading = tooltip.getFacet("loading");
if (loading != null && loading.isRendered()) {
loading.encodeAll(context);
} else {
writer.writeText("Loading...", null);
}
writer.endElement(getMarkupElement(tooltip));
}
private String getMarkupElement(AbstractTooltip component) {
switch (component.getLayout()) {
case block:
return HtmlConstants.DIV_ELEM;
case inline:
return HtmlConstants.SPAN_ELEM;
default:
throw new IllegalStateException("Unknown tooltip layout (=" + component.getLayout() + ")");
}
}
@Override
protected String getStyleClass(UIComponent component) {
return concatClasses("rf-tt", attributeAsString(component, "styleClass"));
}
@Override
protected JSObject getScriptObject(FacesContext context, UIComponent component) {
return new JSObject("RichFaces.ui.Tooltip", component.getClientId(context), getScriptObjectOptions(context, component));
}
@Override
protected Map getScriptObjectOptions(FacesContext context, UIComponent component) {
AbstractTooltip tooltip = (AbstractTooltip) component;
Map options = new HashMap();
RenderKitUtils.addToScriptHash(options, "ajax", getAjaxOptions(context, tooltip), TooltipMode.DEFAULT);
Positioning jointPoint = tooltip.getJointPoint();
if (jointPoint == null) {
jointPoint = org.richfaces.component.Positioning.DEFAULT;
}
Positioning direction = tooltip.getDirection();
if (direction == null) {
direction = org.richfaces.component.Positioning.DEFAULT;
}
RenderKitUtils.addToScriptHash(options, "jointPoint", jointPoint.getValue(), Positioning.DEFAULT.getValue());
RenderKitUtils.addToScriptHash(options, "direction", direction.getValue(), Positioning.DEFAULT.getValue());
RenderKitUtils.addToScriptHash(options, "attached", tooltip.isAttached(), true);
RenderKitUtils.addToScriptHash(options, "offset", getOffset(tooltip));
RenderKitUtils.addToScriptHash(options, "mode", tooltip.getMode(), TooltipMode.DEFAULT);
RenderKitUtils.addToScriptHash(options, "hideDelay", tooltip.getHideDelay(), 0);
RenderKitUtils.addToScriptHash(options, "hideEvent", tooltip.getHideEvent(), "mouseleave");
RenderKitUtils.addToScriptHash(options, "showDelay", tooltip.getShowDelay(), 0);
RenderKitUtils.addToScriptHash(options, "showEvent", tooltip.getShowEvent(), "mouseenter");
RenderKitUtils.addToScriptHash(options, "followMouse", tooltip.isFollowMouse(), true);
String target = tooltip.getTarget();
UIComponent targetComponent = RENDERER_UTILS.findComponentFor(component, target);
if (targetComponent != null) {
target = targetComponent.getClientId();
}
RenderKitUtils.addToScriptHash(options, "target", target);
addEventOption(context, tooltip, options, HIDE);
addEventOption(context, tooltip, options, SHOW);
addEventOption(context, tooltip, options, BEFORE_HIDE);
addEventOption(context, tooltip, options, BEFORE_SHOW);
return options;
}
public Integer[] getOffset(AbstractTooltip tooltip) {
int horizontalOffset = tooltip.getHorizontalOffset();
int verticalOffset = tooltip.getVerticalOffset();
if (horizontalOffset == Integer.MIN_VALUE) {
horizontalOffset = 10;
}
if (verticalOffset == Integer.MIN_VALUE) {
verticalOffset = 10;
}
return new Integer[] { horizontalOffset, verticalOffset };
}
private void encodeContentEnd(ResponseWriter writer, FacesContext context, AbstractTooltip tooltip) throws IOException {
writer.endElement(getMarkupElement(tooltip));
}
@Override
protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
encodeContentEnd(writer, context, (AbstractTooltip) component);
writer.endElement(getMarkupElement((AbstractTooltip) component));
writer.endElement(getMarkupElement((AbstractTooltip) component));
writeJavaScript(writer, context, component);
writer.endElement(getMarkupElement((AbstractTooltip) component));
}
protected void writeJavaScript(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
Object script = getScriptObject(context, component);
if (script == null) {
return;
}
JavaScriptService javaScriptService = ServiceTracker.getService(JavaScriptService.class);
javaScriptService.addScript(context, script);
}
public void encodeMetaComponent(FacesContext context, UIComponent component, String metaComponentId) throws IOException {
if (AbstractTooltip.CONTENT_META_COMPONENT_ID.equals(metaComponentId)) {
AbstractTooltip tooltip = (AbstractTooltip) component;
PartialResponseWriter writer = context.getPartialViewContext().getPartialResponseWriter();
writer.startUpdate(tooltip.getClientId(context) + ":" + AbstractTooltip.CONTENT_META_COMPONENT_ID);
encodeContentBegin(writer, context, tooltip);
for (UIComponent child : tooltip.getChildren()) {
child.encodeAll(context);
}
encodeContentEnd(writer, context, tooltip);
writer.endUpdate();
}
}
public void decodeMetaComponent(FacesContext context, UIComponent component, String metaComponentId) {
throw new UnsupportedOperationException();
}
@Override
protected Class extends UIComponent> getComponentClass() {
return AbstractTooltip.class;
}
@Override
protected void doEncodeChildren(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException {
AbstractTooltip tooltip = (AbstractTooltip) component;
if (tooltip.getMode() == TooltipMode.client) {
if (tooltip.getChildCount() > 0) {
for (UIComponent kid : tooltip.getChildren()) {
kid.encodeAll(context);
}
}
}
}
@Override
public boolean getRendersChildren() {
return true;
}
}