View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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 }