View Javadoc
1   /**
2    * This file Copyright (c) 2010-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.vaadin.gwt.client.form.widget;
35  
36  import info.magnolia.ui.vaadin.gwt.client.form.formsection.widget.InlineMessageWidget;
37  
38  import com.google.gwt.dom.client.Element;
39  import com.google.gwt.dom.client.SpanElement;
40  import com.google.gwt.event.dom.client.BlurEvent;
41  import com.google.gwt.event.dom.client.BlurHandler;
42  import com.google.gwt.event.dom.client.ClickEvent;
43  import com.google.gwt.event.dom.client.FocusEvent;
44  import com.google.gwt.event.dom.client.FocusHandler;
45  import com.google.gwt.event.dom.client.HasBlurHandlers;
46  import com.google.gwt.event.dom.client.HasFocusHandlers;
47  import com.google.gwt.event.shared.HandlerRegistration;
48  import com.google.gwt.regexp.shared.MatchResult;
49  import com.google.gwt.regexp.shared.RegExp;
50  import com.google.gwt.user.client.DOM;
51  import com.google.gwt.user.client.ui.Button;
52  import com.google.gwt.user.client.ui.FlowPanel;
53  import com.google.gwt.user.client.ui.Widget;
54  import com.google.gwt.user.client.ui.impl.FocusImpl;
55  import com.vaadin.client.ui.aria.AriaHelper;
56  
57  /**
58   * Wrapper widget that provides help and error indication.
59   */
60  public class FormFieldWrapper extends FlowPanel implements HasFocusHandlers, HasBlurHandlers {
61  
62      private final static RegExp localisedPropertyCaptionPattern = RegExp.compile("^(.+)\\s(\\([a-zA-Z]{2}\\))$");
63  
64      private Element label = DOM.createDiv();
65  
66      private Element fieldWrapper = DOM.createDiv();
67  
68      private Element root;
69  
70      private Element requirementAsterisk = null;
71  
72      private final HelpIconWidgetclient/form/widget/HelpIconWidget.html#HelpIconWidget">HelpIconWidget helpButton = new HelpIconWidget();
73  
74      private Button errorAction = new Button();
75  
76      private InlineMessageWidget errorSection = null;
77  
78      private InlineMessageWidget helpSection = null;
79  
80      private String helpDescription = null;
81  
82      private Widget field = null;
83  
84      public FormFieldWrapper() {
85          super();
86          addStyleName("v-form-field-section");
87          root = super.getElement();
88          construct();
89          setHelpEnabled(false);
90          helpButton.addDomHandler(event -> {
91              if (helpSection == null) {
92                  showHelp();
93              } else {
94                  hideHelp();
95              }
96          }, ClickEvent.getType());
97  
98      }
99  
100     public void hideHelp() {
101         if (helpSection != null) {
102             remove(helpSection);
103         }
104         helpSection = null;
105         helpButton.setHighlighted(false);
106     }
107 
108     public void showHelp() {
109         if (helpDescription == null || "".equals(helpDescription)) {
110             return;
111         }
112         helpSection = InlineMessageWidget.createHelpMessage();
113         helpSection.setMessage(helpDescription);
114         add(helpSection, root);
115         helpButton.setHighlighted(true);
116     }
117 
118     private void construct() {
119         label.addClassName("v-form-field-label");
120         fieldWrapper.addClassName("v-form-field-container");
121         errorAction.addStyleName("action-validation");
122 
123         root.appendChild(label);
124         root.appendChild(fieldWrapper);
125         add(helpButton, fieldWrapper);
126         add(errorAction, fieldWrapper);
127     }
128 
129     public void showError(final String errorDescription) {
130         helpButton.setVisible(false);
131         errorAction.setVisible(true);
132         fieldWrapper.addClassName("validation-highlight");
133         if (errorSection == null) {
134             errorSection = InlineMessageWidget.createErrorMessage();
135         }
136         errorSection.setMessage(errorDescription);
137         add(errorSection, root);
138     }
139 
140     public void setCaption(String caption) {
141         final MatchResult localisedPropertyMatcher = localisedPropertyCaptionPattern.exec(caption);
142         if (localisedPropertyMatcher != null && localisedPropertyMatcher.getGroupCount() > 2) {
143             caption = localisedPropertyMatcher.getGroup(1);
144             label.setInnerText(caption);
145 
146             final Element localeLabel = SpanElement.as(DOM.createSpan());
147             localeLabel.setClassName("locale-label");
148             localeLabel.setInnerText(localisedPropertyMatcher.getGroup(2));
149 
150             if (requirementAsterisk != null  && label.isOrHasChild(requirementAsterisk)) {
151                 label.insertAfter(localeLabel, requirementAsterisk);
152             } else {
153                 label.insertFirst(localeLabel);
154             }
155         } else {
156             label.setInnerText(caption);
157         }
158 
159         if (caption != null) {
160             label.setTitle(caption);
161         }
162     }
163 
164     public void setRequired(boolean required) {
165         if (required) {
166             if (requirementAsterisk == null) {
167                 requirementAsterisk = SpanElement.as(DOM.createSpan());
168                 requirementAsterisk.setClassName("requiredfield");
169                 requirementAsterisk.setInnerText("*");
170             }
171             label.insertFirst(requirementAsterisk);
172         } else if (requirementAsterisk != null && label.isOrHasChild(requirementAsterisk)) {
173             label.removeChild(requirementAsterisk);
174         }
175     }
176 
177     @Override
178     public void add(Widget child) {
179         add(child, fieldWrapper);
180     }
181 
182     public void setField(Widget child) {
183         if (this.field != null) {
184             remove(field);
185         }
186         this.field = child;
187         if (child != null) {
188             child.removeFromParent();
189             AriaHelper.bindCaption(child, label);
190             getChildren().add(child);
191             fieldWrapper.insertBefore(child.getElement(), helpButton.getElement());
192             adopt(child);
193         }
194     }
195 
196     public boolean isDisplayingHelpSection() {
197         return helpSection != null;
198     }
199 
200     public void clearError() {
201         if (errorSection != null) {
202             remove(errorSection);
203             errorSection = null;
204         }
205         fieldWrapper.removeClassName("validation-highlight");
206         errorAction.setVisible(false);
207         if (helpDescription != null && !"".equals(helpDescription)) {
208             helpButton.setVisible(true);
209         }
210     }
211 
212     public void setHelpEnabled(boolean isHelpEnabled) {
213         helpButton.setVisible(helpDescription != null && !"".equals(helpDescription) && !errorAction.isVisible());
214         if (!isHelpEnabled && helpSection != null) {
215             hideHelp();
216             return;
217         }
218         if (isHelpEnabled && helpButton.isVisible() && helpSection == null) {
219             showHelp();
220         }
221     }
222 
223     public void setHelpDescription(String description) {
224         this.helpDescription = description;
225         if (helpSection != null && getWidgetIndex(helpSection) >= 0) {
226             helpSection.setMessage(helpDescription);
227         }
228         if (description != null && !"".equals(description)) {
229             helpButton.setVisible(true);
230         } else {
231             helpButton.setVisible(false);
232         }
233     }
234 
235     public void focusField() {
236         if (field != null) {
237             FocusImpl.getFocusImplForWidget().focus(field.getElement());
238         }
239     }
240 
241     public Widget getField() {
242         return field;
243     }
244 
245     @Override
246     public HandlerRegistration addFocusHandler(FocusHandler handler) {
247         return field.addDomHandler(handler, FocusEvent.getType());
248     }
249 
250     @Override
251     public HandlerRegistration addBlurHandler(BlurHandler handler) {
252         return field.addDomHandler(handler, BlurEvent.getType());
253     }
254 }