1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.internal.renderkit.renderer;
21
22 import org.apache.myfaces.tobago.context.Markup;
23 import org.apache.myfaces.tobago.internal.component.AbstractUISelectBoolean;
24 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
25 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
26 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
27 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
28 import org.apache.myfaces.tobago.renderkit.css.CssItem;
29 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
30 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
31 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
32 import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
33 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import javax.faces.context.FacesContext;
38 import java.io.IOException;
39 import java.lang.invoke.MethodHandles;
40
41 public class SelectBooleanCheckboxRenderer<T extends AbstractUISelectBoolean>
42 extends MessageLayoutRendererBase<T> {
43
44 private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
45
46 @Override
47 protected boolean isOutputOnly(T component) {
48 return component.isDisabled() || component.isReadonly();
49 }
50
51 @Override
52 public void decodeInternal(final FacesContext facesContext, final T component) {
53
54 if (isOutputOnly(component)) {
55 return;
56 }
57
58 final String newValue = facesContext.getExternalContext()
59 .getRequestParameterMap().get(component.getClientId(facesContext));
60
61 if (LOG.isDebugEnabled()) {
62 LOG.debug("new value = '" + newValue + "'");
63 }
64
65 component.setSubmittedValue("true".equals(newValue) ? "true" : "false");
66
67 decodeClientBehaviors(facesContext, component);
68 }
69
70 @Override
71 public HtmlElements getComponentTag() {
72 return HtmlElements.TOBAGO_SELECT_BOOLEAN_CHECKBOX;
73 }
74
75 @Override
76 protected void encodeBeginField(final FacesContext facesContext, final T component) throws IOException {
77 final TobagoResponseWriter writer = getResponseWriter(facesContext);
78
79 final String clientId = component.getClientId(facesContext);
80 final String fieldId = component.getFieldId(facesContext);
81 final String currentValue = getCurrentValue(facesContext, component);
82 final boolean checked = "true".equals(currentValue);
83 final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, component);
84 final boolean disabled = component.isDisabled();
85 final LabelWithAccessKey label = new LabelWithAccessKey(component, true);
86 final String itemLabel = component.getItemLabel();
87 final String itemImage = component.getItemImage();
88 final Markup markup = component.getMarkup();
89
90 writer.startElement(HtmlElements.TOBAGO_SELECT_BOOLEAN_CHECKBOX);
91 writer.writeIdAttribute(clientId);
92 writer.writeClassAttribute(
93 getTobagoClass(),
94 getTobagoClass().createMarkup(markup),
95 getOuterCssItems(facesContext, component),
96 component.getCustomClass());
97
98 HtmlRendererUtils.writeDataAttributes(facesContext, writer, component);
99 if (title != null) {
100 writer.writeAttribute(HtmlAttributes.TITLE, title, true);
101 }
102
103 writer.startElement(HtmlElements.INPUT);
104 writer.writeClassAttribute(BootstrapClass.FORM_CHECK_INPUT);
105 writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
106 writer.writeAttribute(HtmlAttributes.VALUE, "true", false);
107 writer.writeNameAttribute(clientId);
108 writer.writeIdAttribute(fieldId);
109 writer.writeAttribute(HtmlAttributes.CHECKED, checked);
110 writer.writeAttribute(HtmlAttributes.READONLY, component.isReadonly());
111 writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
112 writer.writeAttribute(HtmlAttributes.REQUIRED, component.isRequired());
113 renderFocus(clientId, component.isFocus(), component.isError(), facesContext, writer);
114 writer.writeAttribute(HtmlAttributes.TABINDEX, component.getTabIndex());
115 writer.endElement(HtmlElements.INPUT);
116
117 writer.startElement(HtmlElements.LABEL);
118 writer.writeClassAttribute(BootstrapClass.FORM_CHECK_LABEL);
119 if (!disabled && label.getAccessKey() != null) {
120 writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
121 AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), clientId);
122 }
123 writer.writeAttribute(HtmlAttributes.FOR, fieldId, false);
124 if (itemImage != null) {
125 writer.startElement(HtmlElements.IMG);
126 writer.writeAttribute(HtmlAttributes.SRC, itemImage, true);
127 writer.writeAttribute(HtmlAttributes.ALT, "", false);
128 writer.endElement(HtmlElements.IMG);
129 }
130 if (itemLabel != null && component.getLabel() == null && component.getAccessKey() != null) {
131 if (itemLabel.contains(Character.toString(component.getAccessKey()))) {
132 HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
133 }
134 } else if (itemLabel != null) {
135 writer.writeText(itemLabel);
136 }
137 writer.endElement(HtmlElements.LABEL);
138 }
139
140 protected TobagoClass getTobagoClass() {
141 return TobagoClass.SELECT_BOOLEAN_CHECKBOX;
142 }
143
144 @Override
145 protected void encodeEndField(final FacesContext facesContext, final T component) throws IOException {
146 final TobagoResponseWriter writer = getResponseWriter(facesContext);
147
148 writer.endElement(HtmlElements.TOBAGO_SELECT_BOOLEAN_CHECKBOX);
149
150 encodeBehavior(writer, facesContext, component);
151 }
152
153 protected CssItem[] getOuterCssItems(final FacesContext facesContext, final AbstractUISelectBoolean select) {
154 final boolean insideCommand = isInside(facesContext, HtmlElements.COMMAND);
155 final boolean colFromLabel = !select.isLabelLayoutSkip() && !insideCommand;
156 return new CssItem[]{
157 BootstrapClass.FORM_CHECK,
158 colFromLabel ? BootstrapClass.COL_FORM_LABEL : null,
159 insideCommand ? BootstrapClass.DROPDOWN_ITEM : null,
160 };
161 }
162
163 @Override
164 protected String getFieldId(final FacesContext facesContext, final T component) {
165 return component.getFieldId(facesContext);
166 }
167 }