Início > Programação > Apresentando Tooltip no Componente SelectOneRadio

Apresentando Tooltip no Componente SelectOneRadio

Teoricamente, os componentes de quaisquer implementações de JSF que lidem com o SelectItem deveriam dar suporte à propriedade itemDescription. Por algum motivo, o componente SelectOneRadio do Primefaces não faz nada com essa propriedade. Vi esse comportamento quando esperava que a configuração abaixo apresentasse dois tooltips: “Tootip1” e “Tooltip2” dependendo do radio button onde o mouse estivesse posicionado:

   <p:selectOneRadio value="#{testeMB.propriedade}" >
      <f:selectItem itemLabel="Tooltip1" itemValue="valor1" itemDescription="Tooltip1"/>
      <f:selectItem itemLabel="Tooltip2" itemValue="valor2" itemDescription="Tooltip2"/>
   </p:selectOneRadio>

Tentei utilizar o componente [p:tooltip] do Primefaces, mas ele está vinculado ao SelectOneRadio como um todo e não me daria a granularidade que eu precisava. Encontrei uma solução interessante aqui. A ideia é corrigir modificar a implementação do SelectOneRadioRenderer para transformar a propriedade itemDescription do SelectItem na propriedade title do componente html renderizado:

import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;
import org.primefaces.component.selectoneradio.SelectOneRadio;
import org.primefaces.util.HTML;

public class SelectOneRadioRenderer extends org.primefaces.component.selectoneradio.SelectOneRadioRenderer {
	@Override
	protected void encodeOptionLabel(FacesContext context, SelectOneRadio radio, String containerClientId,
			SelectItem option, boolean disabled) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		String label = option.getLabel();
		String description = option.getDescription();
		writer.startElement("label", null);
		writer.writeAttribute("for", containerClientId, null);
		if (disabled) {
			writer.writeAttribute("class", "ui-state-disabled", null);
		}
		/*
		 * Adicionando o itemDescription como valor do atributo title do label.
		 */
		writer.writeAttribute("title", description, null);
		if (label != null) {
			if (option.isEscape())
				writer.writeText(label, null);
			else
				writer.write(label);
		}
		writer.endElement("label");
	}

	@Override
	protected void encodeOption(FacesContext context, SelectOneRadio radio, SelectItem option, String id, String name,
			Converter converter, boolean selected, boolean disabled) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		String itemValueAsString = getOptionAsString(context, radio, converter, option.getValue());
		String styleClass = radio.isPlain() ? HTML.RADIOBUTTON_NATIVE_CLASS : HTML.RADIOBUTTON_CLASS;
		writer.startElement("td", null);
		writer.startElement("div", null);
		writer.writeAttribute("class", styleClass, null);
		encodeOptionInput(context, radio, id, name, selected, disabled, itemValueAsString);
		/*
		 * Substituicao do metodo original para passar o item como parametro.
		 */
		encodeOptionOutput(context, radio, selected, disabled, option);
		/*
		 * Metodo original.
		 */
		// encodeOptionOutput(context, radio, selected, disabled);
		writer.endElement("div");
		writer.endElement("td");
		writer.startElement("td", null);
		encodeOptionLabel(context, radio, id, option, disabled);
		writer.endElement("td");
	}

	/**
	 * Esse método foi susbstituido por
	 * {@link #encodeOptionOutput(FacesContext, SelectOneRadio, boolean, boolean, SelectItem)} para que seja possivel o
	 * acesso as configuracoes do item.
	 */
	@Override
	protected void encodeOptionOutput(FacesContext context, SelectOneRadio radio, boolean selected, boolean disabled)
			throws IOException {
		// Nada a fazer
	}

	private void encodeOptionOutput(FacesContext context, SelectOneRadio radio, boolean selected, boolean disabled,
			SelectItem option) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		String boxClass = HTML.RADIOBUTTON_BOX_CLASS;
		boxClass = selected ? boxClass + " ui-state-active" : boxClass;
		boxClass = disabled ? boxClass + " ui-state-disabled" : boxClass;
		boxClass = !radio.isValid() ? boxClass + " ui-state-error" : boxClass;
		String iconClass = selected ? HTML.RADIOBUTTON_CHECKED_ICON_CLASS :
                  HTML.RADIOBUTTON_UNCHECKED_ICON_CLASS;
		writer.startElement("div", null);
		writer.writeAttribute("class", boxClass, null);
		writer.startElement("span", null);
		writer.writeAttribute("class", iconClass, null);
		/*
		 * Atribuindo a descricao ao span. O correto seria fazer a atribuicao do valor a
                 * propriedade input construida em encodeOptionInput, porem o span fica na
                 * frente do input capturando eventos de mouse.
		 */
		writer.writeAttribute("title", option.getDescription(), null);
		writer.endElement("span");
		writer.endElement("div");
	}
}

Dois pontos merecem atenção. Primeiro, cada SelectItem será convertido principalmente em um label e um input do tipo “radio” fora spans, divs e uma estrutura de tabela. Segundo, o title deve ser configurado no label e no span, pois o span fica acima do input e está capturando os eventos do mouse. Por último, basta adicionar esse renderer no faces-config.xml:

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
	version="2.1">
<application>
    <render-kit >      
        <renderer>
            <component-family>org.primefaces.component</component-family>
            <renderer-type>org.primefaces.component.SelectOneRadioRenderer</renderer-type>
            <renderer-class>pacote.renderer.SelectOneRadioRenderer</renderer-class>
        </renderer>
    </render-kit>
</application>
</faces-config>
Anúncios
  1. Nenhum comentário ainda.
  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: