Add additional class names and style to components and error indicators to distinguish different error levels.
Vaadin 8 implementation of #9816. Cherry picked changes and added compatibility package component changes and tests.
Resolves #3139
<li><tt>DataCommunicator</tt> method <tt>getDataProviderSize</tt> is now <tt>public</tt>, not <tt>protected</tt>.</li>
<li><tt>Binder</tt> method <tt>getBindings</tt> now returns a Collection, not a Set.</li>
<li><tt>BindingBuilder</tt> now works like a proper builder. Adding a converter will not mark Binding as <tt>bound</tt> allowing chaining to the same object.</li>
+ <li><tt>ErrorLevel</tt> is removed from <tt>ErrorMessage</tt> and now <tt>com.vaadin.shared.ui.ErrorLevel</tt> should be used.</li>
+ <li>Error indicators are now <tt><span class="v-errorindicator"></span></tt> elements.</li>
<h2>For incompatible or behaviour-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2>
public static final String REQUIRED_EXT = "-required";
public static final String ERROR_EXT = "-error";
+
+ /**
+ * Style name and style name prefix for the error indicator element.
+ */
+ public static final String STYLE_NAME_ERROR_INDICATOR = "v-errorindicator";
}
package com.vaadin.client;
import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.shared.util.SharedUtil;
+/**
+ * An object that contains information about a tooltip, such as the tooltip's
+ * title, error message, error level and an ID.
+ */
public class TooltipInfo {
private String title;
private String errorMessageHtml;
+ private ErrorLevel errorLevel;
+
// Contains the tooltip's identifier. If a tooltip's contents and this
// identifier haven't changed, the tooltip won't be updated in subsequent
// events.
private Object identifier;
+ /**
+ * Constructs a new tooltip info instance.
+ */
public TooltipInfo() {
}
+ /**
+ * Constructs a new tooltip info instance.
+ *
+ * @param tooltip
+ * tooltip title
+ */
public TooltipInfo(String tooltip) {
this(tooltip, ContentMode.PREFORMATTED);
}
/**
* Constructs a new instance using the {@code tooltip} for the title and
* {@code errorMessage} as a description.
- *
+ *
* @param tooltip
* tooltip title
* @param errorMessage
* error description
- *
+ *
* @deprecated use {@link #TooltipInfo(String, ContentMode, String)} instead
*/
@Deprecated
/**
* Constructs a new instance using the {@code tooltip} for the title,
* {@code errorMessage} as a description and {@code identifier} as its id.
- *
+ *
* @param tooltip
* tooltip title
* @param errorMessage
* error description
* @param identifier
- *
+ * the tooltip's identifier
+ *
* @deprecated use {@link #TooltipInfo(String, ContentMode, String, Object)}
* instead
*/
this(tooltip, ContentMode.HTML, errorMessage, identifier);
}
+ /**
+ * Constructs a new instance using the {@code tooltip} for the title,
+ * {@code errorMessage} as a description, {@code identifier} as its id and
+ * {@code errorLevel} as the error level.
+ *
+ * @param tooltip
+ * tooltip title
+ * @param errorMessage
+ * error description
+ * @param identifier
+ * the tooltip's identifier
+ * @param errorLevel
+ * error level
+ *
+ * @deprecated use {@link #TooltipInfo(String, ContentMode, String, Object,
+ * ErrorLevel)} instead
+ * @since 8.2
+ */
+ @Deprecated
+ public TooltipInfo(String tooltip, String errorMessage, Object identifier,
+ ErrorLevel errorLevel) {
+ this(tooltip, ContentMode.HTML, errorMessage, identifier, errorLevel);
+ }
+
+ /**
+ * Constructs a new tooltip info instance.
+ *
+ * @param tooltip
+ * tooltip title
+ * @param mode
+ * content mode
+ */
public TooltipInfo(String tooltip, ContentMode mode) {
setTitle(tooltip);
setContentMode(mode);
}
+ /**
+ * Constructs a new tooltip info instance.
+ *
+ * @param tooltip
+ * tooltip title
+ * @param mode
+ * content mode
+ * @param errorMessage
+ * error message
+ */
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage) {
this(tooltip, mode, errorMessage, null);
}
+ /**
+ * Constructs a new tooltip info instance.
+ *
+ * @param tooltip
+ * tooltip title
+ * @param mode
+ * content mode
+ * @param errorMessage
+ * error message
+ * @param identifier
+ * the tooltip's identifier
+ */
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage,
Object identifier) {
+ this(tooltip, mode, errorMessage, identifier, null);
+ }
+
+ /**
+ * Constructs a new tooltip info instance.
+ *
+ * @param tooltip
+ * tooltip title
+ * @param mode
+ * content mode
+ * @param errorMessage
+ * error message
+ * @param identifier
+ * the tooltip's identifier
+ * @param errorLevel
+ * error level
+ */
+ public TooltipInfo(String tooltip, ContentMode mode, String errorMessage,
+ Object identifier, ErrorLevel errorLevel) {
setIdentifier(identifier);
setTitle(tooltip);
setContentMode(mode);
setErrorMessage(errorMessage);
+ setErrorLevel(errorLevel);
}
+ /**
+ * Sets the tooltip's identifier.
+ *
+ * @param identifier
+ * the identifier to set
+ */
public void setIdentifier(Object identifier) {
this.identifier = identifier;
}
+ /**
+ * Gets the tooltip's identifier.
+ *
+ * @return the identifier
+ */
public Object getIdentifier() {
return identifier;
}
+ /**
+ * Gets the tooltip title.
+ *
+ * @return the title
+ */
public String getTitle() {
return title;
}
+ /**
+ * Sets the tooltip title.
+ *
+ * @param title
+ * the title to set
+ */
public void setTitle(String title) {
this.title = title;
}
+ /**
+ * Gets the error message.
+ *
+ * @return the error message
+ */
public String getErrorMessage() {
return errorMessageHtml;
}
+ /**
+ * Sets the error message.
+ *
+ * @param errorMessage
+ * the error message to set
+ */
public void setErrorMessage(String errorMessage) {
errorMessageHtml = errorMessage;
}
+ /**
+ * Gets the tooltip title's content mode.
+ *
+ * @return the content mode
+ */
public ContentMode getContentMode() {
return contentMode;
}
+ /**
+ * Sets the tooltip title's content mode.
+ *
+ * @param contentMode
+ * the content mode to set
+ */
public void setContentMode(ContentMode contentMode) {
this.contentMode = contentMode;
}
+ /**
+ * Gets the error level.
+ *
+ * @return the error level
+ * @since
+ */
+ public ErrorLevel getErrorLevel() {
+ return errorLevel;
+ }
+
+ /**
+ * Sets the error level.
+ *
+ * @param errorLevel
+ * the error level to set
+ * @since
+ */
+ public void setErrorLevel(ErrorLevel errorLevel) {
+ this.errorLevel = errorLevel;
+ }
+
/**
* Checks is a message has been defined for the tooltip.
*
|| (errorMessageHtml != null && !errorMessageHtml.isEmpty());
}
+ /**
+ * Indicates whether another tooltip info instance is equal to this one. Two
+ * instances are equal if their title, error message, error level and
+ * identifier are equal.
+ *
+ * @param other
+ * the reference tooltip info instance with which to compare
+ * @return {@code true} if the instances are equal, {@code false} otherwise
+ */
public boolean equals(TooltipInfo other) {
return (other != null && SharedUtil.equals(other.title, title)
&& SharedUtil.equals(other.errorMessageHtml, errorMessageHtml)
+ && SharedUtil.equals(other.errorLevel, errorLevel)
&& other.identifier == identifier);
}
}
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHTML;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.HasErrorIndicator;
+import com.vaadin.client.ui.HasErrorIndicatorElement;
import com.vaadin.client.ui.HasRequiredIndicator;
import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.ImageIcon;
import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.ui.ComponentStateUtil;
+import com.vaadin.shared.ui.ErrorLevel;
-public class VCaption extends HTML {
+public class VCaption extends HTML implements HasErrorIndicatorElement {
public static final String CLASSNAME = "v-caption";
AriaHelper.handleInputInvalid(owner.getWidget(), showError);
if (showError) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createDiv();
- DOM.setInnerHTML(errorIndicatorElement, " ");
- DOM.setElementProperty(errorIndicatorElement, "className",
- "v-errorindicator");
+ setErrorIndicatorElementVisible(true);
- DOM.insertChild(getElement(), errorIndicatorElement,
- getInsertPosition(InsertPosition.ERROR));
+ // Hide error indicator from assistive devices
+ Roles.getTextboxRole()
+ .setAriaHiddenState(errorIndicatorElement, true);
- // Hide error indicator from assistive devices
- Roles.getTextboxRole().setAriaHiddenState(errorIndicatorElement,
- true);
- }
- } else if (errorIndicatorElement != null) {
- // Remove existing
- getElement().removeChild(errorIndicatorElement);
- errorIndicatorElement = null;
+ ErrorUtil.setErrorLevelStyle(errorIndicatorElement,
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR,
+ owner.getState().errorLevel);
+ } else {
+ setErrorIndicatorElementVisible(false);
}
return (wasPlacedAfterComponent != placedAfterComponent);
public boolean updateCaptionWithoutOwner(String caption, boolean disabled,
boolean hasDescription, boolean hasError, String iconURL,
String iconAltText) {
+ return updateCaptionWithoutOwner(caption, disabled, hasDescription,
+ hasError, null, iconURL, iconAltText);
+ }
+
+ @Deprecated
+ public boolean updateCaptionWithoutOwner(String caption, boolean disabled,
+ boolean hasDescription, boolean hasError, ErrorLevel errorLevel,
+ String iconURL, String iconAltText) {
boolean wasPlacedAfterComponent = placedAfterComponent;
// Caption is placed after component unless there is some part which
}
if (hasError) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createDiv();
- DOM.setInnerHTML(errorIndicatorElement, " ");
- DOM.setElementProperty(errorIndicatorElement, "className",
- "v-errorindicator");
-
- DOM.insertChild(getElement(), errorIndicatorElement,
- getInsertPosition(InsertPosition.ERROR));
- }
- } else if (errorIndicatorElement != null) {
- // Remove existing
- getElement().removeChild(errorIndicatorElement);
- errorIndicatorElement = null;
+ setErrorIndicatorElementVisible(true);
+ ErrorUtil.setErrorLevelStyle(errorIndicatorElement,
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel);
+ } else {
+ setErrorIndicatorElementVisible(false);
}
return (wasPlacedAfterComponent != placedAfterComponent);
private static Logger getLogger() {
return Logger.getLogger(VCaption.class.getName());
}
+
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil.createErrorIndicatorElement();
+ DOM.insertChild(getElement(), errorIndicatorElement,
+ getInsertPosition(InsertPosition.ERROR));
+ }
+ } else if (errorIndicatorElement != null) {
+ getElement().removeChild(errorIndicatorElement);
+ errorIndicatorElement = null;
+ }
+ }
}
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ui.VOverlay;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
+import com.vaadin.shared.ui.ErrorLevel;
public class VErrorMessage extends FlowPanel {
public static final String CLASSNAME = "v-errormessage";
}
}
+ /**
+ * Sets the correct error level style name for the error message and removes
+ * all previous style names.
+ *
+ * @param errorLevel
+ * error level
+ * @since
+ */
+ public void updateErrorLevel(ErrorLevel errorLevel) {
+ ErrorUtil.setErrorLevelStyle(getStyleElement(), CLASSNAME, errorLevel);
+ }
+
/**
* Shows this error message next to given element.
*
&& !info.getErrorMessage().isEmpty()) {
em.setVisible(true);
em.updateMessage(info.getErrorMessage());
+ em.updateErrorLevel(info.getErrorLevel());
} else {
em.setVisible(false);
}
@Override
public void hide() {
em.updateMessage("");
+ em.updateErrorLevel(null);
description.setHTML("");
updatePosition(null, true);
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.shared.util.SharedUtil;
/**
com.google.gwt.dom.client.Element el, String p)
/*-{
try {
-
+
if (el.currentStyle) {
// IE
return el.currentStyle[p];
} catch (e) {
return "";
}
-
+
}-*/;
/**
try {
el.focus();
} catch (e) {
-
+
}
}-*/;
if ($wnd.document.activeElement) {
return $wnd.document.activeElement;
}
-
+
return null;
}-*/;
/*-{
var top = elem.offsetTop;
var height = elem.offsetHeight;
-
+
if (elem.parentNode != elem.offsetParent) {
top -= elem.parentNode.offsetTop;
}
-
+
var cur = elem.parentNode;
while (cur && (cur.nodeType == 1)) {
if (top < cur.scrollTop) {
if (top + height > cur.scrollTop + cur.clientHeight) {
cur.scrollTop = (top + height) - cur.clientHeight;
}
-
+
var offsetTop = cur.offsetTop;
if (cur.parentNode != cur.offsetParent) {
offsetTop -= cur.parentNode.offsetTop;
}
-
+
top += offsetTop - cur.scrollTop;
cur = cur.parentNode;
}
}
var heightWithoutBorder = cloneElement.offsetHeight;
parentElement.removeChild(cloneElement);
-
+
return heightWithBorder - heightWithoutBorder;
}
}-*/;
int relativeTop = element.getAbsoluteTop() - Window.getScrollTop();
return WidgetUtil.getTouchOrMouseClientY(event) - relativeTop;
}
+
+ /**
+ * Utility methods for displaying error message on components.
+ *
+ * @since 8.2
+ */
+ public static class ErrorUtil {
+
+ /**
+ * Sets the error level style name for the given element and removes all
+ * previously applied error level style names. The style name has the
+ * {@code prefix-errorLevel} format.
+ *
+ * @param element
+ * element to apply the style name to
+ * @param prefix
+ * part of the style name before the error level string
+ * @param errorLevel
+ * error level for which the style will be applied
+ */
+ public static void setErrorLevelStyle(Element element, String prefix,
+ ErrorLevel errorLevel) {
+ for (ErrorLevel errorLevelValue : ErrorLevel.values()) {
+ String className =
+ prefix + "-" + errorLevelValue.toString().toLowerCase();
+ if (errorLevel == errorLevelValue) {
+ element.addClassName(className);
+ } else {
+ element.removeClassName(className);
+ }
+ }
+ }
+
+ /**
+ * Creates an element to use by widgets as an error indicator.
+ *
+ * @return the error indicator element
+ */
+ public static Element createErrorIndicatorElement() {
+ Element indicator = DOM.createSpan();
+ indicator.setClassName(StyleConstants.STYLE_NAME_ERROR_INDICATOR);
+ return indicator;
+ }
+ }
}
import com.vaadin.client.Util;
import com.vaadin.client.VConsole;
import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.extensions.DragSourceExtensionConnector;
Profiler.leave("AbstractComponentConnector.onStateChanged");
}
+ @OnStateChange({"errorMessage", "errorLevel"})
+ private void setErrorLevel() {
+ // Add or remove the widget's error level style name
+ ErrorUtil.setErrorLevelStyle(getWidget().getElement(),
+ getWidget().getStylePrimaryName() + StyleConstants.ERROR_EXT,
+ getState().errorLevel);
+
+ // Add or remove error indicator element
+ if (getWidget() instanceof HasErrorIndicatorElement) {
+ HasErrorIndicatorElement widget = (HasErrorIndicatorElement) getWidget();
+ if (getState().errorMessage != null) {
+ widget.setErrorIndicatorElementVisible(true);
+ ErrorUtil.setErrorLevelStyle(widget.getErrorIndicatorElement(),
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR,
+ getState().errorLevel);
+ } else {
+ widget.setErrorIndicatorElementVisible(false);
+ }
+ }
+ }
+
@Override
public void setWidgetEnabled(boolean widgetEnabled) {
// add or remove v-disabled style name from the widget
@Override
public TooltipInfo getTooltipInfo(Element element) {
return new TooltipInfo(getState().description,
- getState().descriptionContentMode, getState().errorMessage);
+ getState().descriptionContentMode, getState().errorMessage,
+ null, getState().errorLevel);
}
@Override
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.ui;
+
+import com.google.gwt.dom.client.Element;
+
+/**
+ * Implemented by widgets supporting an error indicator.
+ *
+ * @since 8.2
+ */
+public interface HasErrorIndicatorElement {
+
+ /**
+ * Gets the error indicator element.
+ *
+ * @return the error indicator element
+ */
+ Element getErrorIndicatorElement();
+
+ /**
+ * Sets the visibility of the error indicator element.
+ *
+ * @param visible
+ * {@code true} to show the error indicator element, {@code false}
+ * to hide it
+ */
+ void setErrorIndicatorElementVisible(boolean visible);
+}
caption.updateCaptionWithoutOwner(tabState.caption,
!tabState.enabled, hasAttribute(tabState.description),
hasAttribute(tabState.componentError),
+ tabState.componentErrorLevel,
connector.getResourceUrl(
- ComponentConstants.ICON_RESOURCE + tabState.key));
+ ComponentConstants.ICON_RESOURCE + tabState.key),
+ tabState.iconAltText);
}
private boolean hasAttribute(String string) {
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.Util;
import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
-public class VButton extends FocusWidget implements ClickHandler {
+public class VButton extends FocusWidget implements ClickHandler,
+ HasErrorIndicatorElement {
public static final String CLASSNAME = "v-button";
private static final String CLASSNAME_PRESSED = "v-pressed";
public final Element wrapper = DOM.createSpan();
/** For internal use only. May be removed or replaced in the future. */
- public Element errorIndicatorElement;
+ private Element errorIndicatorElement;
/** For internal use only. May be removed or replaced in the future. */
public final Element captionElement = DOM.createSpan();
return ret;
}-*/;
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil.createErrorIndicatorElement();
+ wrapper.insertFirst(errorIndicatorElement);
+ }
+ } else if (errorIndicatorElement != null) {
+ wrapper.removeChild(errorIndicatorElement);
+ errorIndicatorElement = null;
+ }
+ }
}
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.Util;
import com.vaadin.client.VTooltip;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.ui.aria.AriaHelper;
import com.vaadin.client.ui.aria.HandlesAriaInvalid;
import com.vaadin.client.ui.aria.HandlesAriaRequired;
public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox
- implements Field, HandlesAriaInvalid, HandlesAriaRequired {
+ implements Field, HandlesAriaInvalid, HandlesAriaRequired,
+ HasErrorIndicatorElement {
public static final String CLASSNAME = "v-checkbox";
public ApplicationConnection client;
/** For internal use only. May be removed or replaced in the future. */
- public Element errorIndicatorElement;
+ private Element errorIndicatorElement;
/** For internal use only. May be removed or replaced in the future. */
public Icon icon;
public void setAriaInvalid(boolean invalid) {
AriaHelper.handleInputInvalid(getCheckBoxElement(), invalid);
}
+
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil.createErrorIndicatorElement();
+ getElement().appendChild(errorIndicatorElement);
+ DOM.sinkEvents(errorIndicatorElement,
+ VTooltip.TOOLTIP_EVENTS | Event.ONCLICK);
+ }
+ } else if (errorIndicatorElement != null) {
+ getElement().removeChild(errorIndicatorElement);
+ errorIndicatorElement = null;
+ }
+ }
}
import com.vaadin.client.Focusable;
import com.vaadin.client.StyleConstants;
import com.vaadin.client.VTooltip;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.ui.aria.AriaHelper;
import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.ui.ComponentStateUtil;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.shared.ui.MarginInfo;
/**
}
public void updateError(Widget widget, String errorMessage,
- boolean hideErrors) {
+ ErrorLevel errorLevel, boolean hideErrors) {
final ErrorFlag e = widgetToError.get(widget);
if (e != null) {
- e.updateError(errorMessage, hideErrors);
+ e.updateError(errorMessage, errorLevel, hideErrors);
}
}
}
/** For internal use only. May be removed or replaced in the future. */
- public class ErrorFlag extends HTML {
+ public class ErrorFlag extends HTML implements HasErrorIndicatorElement {
private static final String CLASSNAME = VFormLayout.CLASSNAME
+ "-error-indicator";
Element errorIndicatorElement;
return owner;
}
- public void updateError(String errorMessage, boolean hideErrors) {
+ public void updateError(String errorMessage, ErrorLevel errorLevel,
+ boolean hideErrors) {
boolean showError = null != errorMessage;
if (hideErrors) {
showError = false;
AriaHelper.handleInputInvalid(owner.getWidget(), showError);
if (showError) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createDiv();
- DOM.setInnerHTML(errorIndicatorElement, " ");
- DOM.setElementProperty(errorIndicatorElement, "className",
- "v-errorindicator");
- DOM.appendChild(getElement(), errorIndicatorElement);
+ setErrorIndicatorElementVisible(true);
- // Hide the error indicator from screen reader, as this
- // information is set directly at the input field
- Roles.getFormRole()
- .setAriaHiddenState(errorIndicatorElement, true);
- }
+ // Hide the error indicator from screen reader, as this
+ // information is set directly at the input field
+ Roles.getFormRole()
+ .setAriaHiddenState(errorIndicatorElement, true);
+
+ ErrorUtil.setErrorLevelStyle(errorIndicatorElement,
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel);
+ } else {
+ setErrorIndicatorElementVisible(false);
+ }
+ }
+
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil
+ .createErrorIndicatorElement();
+ getElement().appendChild(errorIndicatorElement);
+ }
} else if (errorIndicatorElement != null) {
- DOM.removeChild(getElement(), errorIndicatorElement);
+ getElement().removeChild(errorIndicatorElement);
errorIndicatorElement = null;
}
}
-
}
}
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasEnabled;
import com.vaadin.client.Util;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.shared.ui.BorderStyle;
-public class VLink extends HTML implements ClickHandler, HasEnabled {
+public class VLink extends HTML implements ClickHandler, HasEnabled,
+ HasErrorIndicatorElement {
public static final String CLASSNAME = "v-link";
public int targetHeight;
/** For internal use only. May be removed or replaced in the future. */
- public Element errorIndicatorElement;
+ private Element errorIndicatorElement;
/** For internal use only. May be removed or replaced in the future. */
public final Element anchor = DOM.createAnchor();
this.enabled = enabled;
}
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil.createErrorIndicatorElement();
+ getElement().insertFirst(errorIndicatorElement);
+ }
+ } else if (errorIndicatorElement != null) {
+ getElement().removeChild(errorIndicatorElement);
+ errorIndicatorElement = null;
+ }
+ }
}
import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.StyleConstants;
import com.vaadin.client.Util;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.button.ButtonServerRpc;
-public class VNativeButton extends Button implements ClickHandler {
+public class VNativeButton extends Button implements ClickHandler,
+ HasErrorIndicatorElement {
public static final String CLASSNAME = "v-nativebutton";
public ButtonServerRpc buttonRpcProxy;
/** For internal use only. May be removed or replaced in the future. */
- public Element errorIndicatorElement;
+ private Element errorIndicatorElement;
/** For internal use only. May be removed or replaced in the future. */
public final Element captionElement = DOM.createSpan();
clickPending = false;
}
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil.createErrorIndicatorElement();
+ getElement()
+ .insertBefore(errorIndicatorElement, captionElement);
+ }
+ } else if (errorIndicatorElement != null) {
+ getElement().removeChild(errorIndicatorElement);
+ errorIndicatorElement = null;
+ }
+ }
}
import com.google.gwt.user.client.ui.SimplePanel;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.Focusable;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
-public class VPanel extends SimplePanel
- implements ShortcutActionHandlerOwner, Focusable {
+public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
+ Focusable, HasErrorIndicatorElement {
public static final String CLASSNAME = "v-panel";
DOM.setInnerHTML(captionText, text);
}
- /** For internal use only. May be removed or replaced in the future. */
- public void setErrorIndicatorVisible(boolean showError) {
- if (showError) {
- if (errorIndicatorElement == null) {
- errorIndicatorElement = DOM.createSpan();
- DOM.setElementProperty(errorIndicatorElement, "className",
- "v-errorindicator");
- DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS);
- sinkEvents(Event.MOUSEEVENTS);
- }
- DOM.insertBefore(captionNode, errorIndicatorElement, captionText);
- } else if (errorIndicatorElement != null) {
- DOM.removeChild(captionNode, errorIndicatorElement);
- errorIndicatorElement = null;
- }
- }
-
/** For internal use only. May be removed or replaced in the future. */
public void setIconUri(String iconUri, ApplicationConnection client) {
if (icon != null) {
}
touchScrollHandler.addElement(contentNode);
}
+
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIndicatorElement;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIndicatorElement == null) {
+ errorIndicatorElement = ErrorUtil.createErrorIndicatorElement();
+ DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS);
+ sinkEvents(Event.MOUSEEVENTS);
+ captionNode.insertBefore(errorIndicatorElement, captionText);
+ }
+ } else if (errorIndicatorElement != null){
+ captionNode.removeChild(errorIndicatorElement);
+ errorIndicatorElement = null;
+ }
+ }
}
|| tabState.componentError != null) {
setTooltipInfo(new TooltipInfo(tabState.description,
tabState.descriptionContentMode,
- tabState.componentError, this));
+ tabState.componentError, this,
+ tabState.componentErrorLevel));
} else {
setTooltipInfo(null);
}
boolean ret = updateCaptionWithoutOwner(captionString,
!tabState.enabled, hasAttribute(tabState.description),
hasAttribute(tabState.componentError),
+ tabState.componentErrorLevel,
tab.getTabsheet().connector.getResourceUrl(
ComponentConstants.ICON_RESOURCE + tabState.key),
tabState.iconAltText);
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.StyleConstants;
import com.vaadin.client.VCaption;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
ConnectorFocusAndBlurHandler.addHandlers(this);
}
- @OnStateChange("errorMessage")
- void setErrorMessage() {
- if (null != getState().errorMessage) {
- if (getWidget().errorIndicatorElement == null) {
- getWidget().errorIndicatorElement = DOM.createSpan();
- getWidget().errorIndicatorElement
- .setClassName("v-errorindicator");
- }
- getWidget().wrapper.insertFirst(getWidget().errorIndicatorElement);
-
- } else if (getWidget().errorIndicatorElement != null) {
- getWidget().wrapper.removeChild(getWidget().errorIndicatorElement);
- getWidget().errorIndicatorElement = null;
- }
- }
-
@OnStateChange("resources")
void onResourceChange() {
if (getWidget().icon != null) {
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.StyleConstants;
import com.vaadin.client.VCaption;
import com.vaadin.client.VTooltip;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector;
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
- if (null != getState().errorMessage) {
- getWidget().setAriaInvalid(true);
-
- if (getWidget().errorIndicatorElement == null) {
- getWidget().errorIndicatorElement = DOM.createSpan();
- getWidget().errorIndicatorElement.setInnerHTML(" ");
- DOM.setElementProperty(getWidget().errorIndicatorElement,
- "className", "v-errorindicator");
- DOM.appendChild(getWidget().getElement(),
- getWidget().errorIndicatorElement);
- DOM.sinkEvents(getWidget().errorIndicatorElement,
- VTooltip.TOOLTIP_EVENTS | Event.ONCLICK);
- } else {
- getWidget().errorIndicatorElement.getStyle().clearDisplay();
- }
- } else if (getWidget().errorIndicatorElement != null) {
- getWidget().errorIndicatorElement.getStyle()
- .setDisplay(Display.NONE);
-
- getWidget().setAriaInvalid(false);
- }
+ getWidget().setAriaInvalid(getState().errorMessage != null);
getWidget().setAriaRequired(isRequiredIndicatorVisible());
if (isReadOnly()) {
}
getWidget().table.updateError(component.getWidget(),
- component.getState().errorMessage, hideErrors);
+ component.getState().errorMessage,
+ component.getState().errorLevel, hideErrors);
}
@Override
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.user.client.DOM;
+import com.vaadin.client.StyleConstants;
import com.vaadin.client.VCaption;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.Icon;
// Set link caption
VCaption.setCaptionText(getWidget().captionElement, getState());
- // handle error
- if (null != getState().errorMessage) {
- if (getWidget().errorIndicatorElement == null) {
- getWidget().errorIndicatorElement = DOM.createDiv();
- DOM.setElementProperty(getWidget().errorIndicatorElement,
- "className", "v-errorindicator");
- }
- DOM.insertChild(getWidget().getElement(),
- getWidget().errorIndicatorElement, 0);
- } else if (getWidget().errorIndicatorElement != null) {
- getWidget().errorIndicatorElement.getStyle()
- .setDisplay(Display.NONE);
- }
-
if (getWidget().icon != null) {
getWidget().anchor.removeChild(getWidget().icon.getElement());
getWidget().icon = null;
package com.vaadin.client.ui.nativebutton;
import com.google.gwt.user.client.DOM;
+import com.vaadin.client.StyleConstants;
import com.vaadin.client.VCaption;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
// Set text
VCaption.setCaptionText(getWidget(), getState());
- // handle error
- if (null != getState().errorMessage) {
- if (getWidget().errorIndicatorElement == null) {
- getWidget().errorIndicatorElement = DOM.createSpan();
- getWidget().errorIndicatorElement
- .setClassName("v-errorindicator");
- }
- getWidget().getElement().insertBefore(
- getWidget().errorIndicatorElement,
- getWidget().captionElement);
-
- } else if (getWidget().errorIndicatorElement != null) {
- getWidget().getElement()
- .removeChild(getWidget().errorIndicatorElement);
- getWidget().errorIndicatorElement = null;
- }
-
if (getWidget().icon != null) {
getWidget().getElement().removeChild(getWidget().icon.getElement());
getWidget().icon = null;
slot.setCaptionResizeListener(null);
}
- slot.setCaption(caption, icon, styles, error, showError, required,
- enabled, child.getState().captionAsHtml);
+ slot.setCaption(caption, icon, styles, error,
+ child.getState().errorLevel, showError, required, enabled,
+ child.getState().captionAsHtml);
AriaHelper.handleInputRequired(child.getWidget(), required);
AriaHelper.handleInputInvalid(child.getWidget(), showError);
import com.vaadin.client.LayoutManager;
import com.vaadin.client.StyleConstants;
import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.ui.FontIcon;
+import com.vaadin.client.ui.HasErrorIndicatorElement;
import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.ImageIcon;
import com.vaadin.client.ui.layout.ElementResizeListener;
import com.vaadin.shared.ui.AlignmentInfo;
+import com.vaadin.shared.ui.ErrorLevel;
/**
* Represents a slot which contains the actual widget in the layout.
*/
-public class Slot extends SimplePanel {
+public class Slot extends SimplePanel implements HasErrorIndicatorElement {
private static final String ALIGN_CLASS_PREFIX = "v-align-";
public void setCaption(String captionText, Icon icon, List<String> styles,
String error, boolean showError, boolean required, boolean enabled,
boolean captionAsHtml) {
+ setCaption(captionText, icon, styles, error, null, showError, required,
+ enabled, captionAsHtml);
+ }
+
+ /**
+ * Set the caption of the slot
+ *
+ * @param captionText
+ * The text of the caption
+ * @param icon
+ * The icon
+ * @param styles
+ * The style names
+ * @param error
+ * The error message
+ * @param errorLevel
+ * The error level
+ * @param showError
+ * Should the error message be shown
+ * @param required
+ * Is the (field) required
+ * @param enabled
+ * Is the component enabled
+ * @param captionAsHtml
+ * true if the caption should be rendered as HTML, false
+ * otherwise
+ * @since 8.2
+ */
+ public void setCaption(String captionText, Icon icon, List<String> styles,
+ String error, ErrorLevel errorLevel, boolean showError,
+ boolean required, boolean enabled, boolean captionAsHtml) {
// TODO place for optimization: check if any of these have changed
// since last time, and only run those changes
// Error
if (error != null && showError) {
- if (errorIcon == null) {
- errorIcon = DOM.createSpan();
- errorIcon.setClassName("v-errorindicator");
- }
- caption.appendChild(errorIcon);
- } else if (errorIcon != null) {
- errorIcon.removeFromParent();
- errorIcon = null;
+ setErrorIndicatorElementVisible(true);
+ ErrorUtil.setErrorLevelStyle(getErrorIndicatorElement(),
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel);
+ } else {
+ setErrorIndicatorElementVisible(false);
}
if (caption != null) {
return hasRelativeWidth();
}
}
+
+ @Override
+ public Element getErrorIndicatorElement() {
+ return errorIcon;
+ }
+
+ @Override
+ public void setErrorIndicatorElementVisible(boolean visible) {
+ if (visible) {
+ if (errorIcon == null) {
+ errorIcon = ErrorUtil.createErrorIndicatorElement();
+ }
+ caption.appendChild(errorIcon);
+ } else if (errorIcon != null) {
+ errorIcon.removeFromParent();
+ errorIcon = null;
+ }
+ }
}
getWidget().setIconUri(null, client);
}
- getWidget().setErrorIndicatorVisible(isErrorIndicatorVisible());
-
// We may have actions attached to this panel
if (uidl.getChildCount() > 0) {
final int cnt = uidl.getChildCount();
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.StyleConstants;
import com.vaadin.client.VCaption;
import com.vaadin.client.VTooltip;
+import com.vaadin.client.WidgetUtil.ErrorUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler;
getWidget().errorIndicatorElement = DOM.createSpan();
getWidget().errorIndicatorElement.setInnerHTML(" ");
DOM.setElementProperty(getWidget().errorIndicatorElement,
- "className", "v-errorindicator");
+ "className", StyleConstants.STYLE_NAME_ERROR_INDICATOR);
DOM.appendChild(getWidget().getElement(),
getWidget().errorIndicatorElement);
DOM.sinkEvents(getWidget().errorIndicatorElement,
} else {
getWidget().errorIndicatorElement.getStyle().clearDisplay();
}
+
+ ErrorUtil.setErrorLevelStyle(getWidget().errorIndicatorElement,
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR,
+ getState().errorLevel);
+
} else if (getWidget().errorIndicatorElement != null) {
getWidget().errorIndicatorElement.getStyle()
.setDisplay(Display.NONE);
if (null != getState().errorMessage) {
getWidget().errorMessage.updateMessage(getState().errorMessage);
+ getWidget().errorMessage.updateErrorLevel(getState().errorLevel);
getWidget().errorMessage.setVisible(true);
} else {
getWidget().errorMessage.setVisible(false);
import com.vaadin.data.Binder;
import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.server.ErrorMessage;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.ErrorMessageProducer;
import com.vaadin.server.UserError;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.v7.data.Validator.InvalidValueException;
/**
import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.server.AbstractErrorMessage.ContentMode;
import com.vaadin.server.ErrorMessage;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.ErrorMessageProducer;
import com.vaadin.server.UserError;
import com.vaadin.server.VaadinServlet;
+import com.vaadin.shared.ui.ErrorLevel;
/**
* Interface that implements a method for validating if an {@link Object} is
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Component;
import org.junit.Before;
import org.junit.Test;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.FileResource;
import com.vaadin.server.Responsive;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.UserError;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Label;
import java.util.ArrayList;
import java.util.List;
+import com.vaadin.shared.ui.ErrorLevel;
+
/**
* Base class for component error messages.
*
import java.util.Collection;
import java.util.Iterator;
+import com.vaadin.shared.ui.ErrorLevel;
+
/**
* Class for combining multiple error messages together.
*
*/
public CompositeErrorMessage(ErrorMessage... errorMessages) {
super(null);
- setErrorLevel(ErrorLevel.INFORMATION);
+ setErrorLevel(ErrorLevel.INFO);
for (ErrorMessage errorMessage : errorMessages) {
addErrorMessage(errorMessage);
public CompositeErrorMessage(
Collection<? extends ErrorMessage> errorMessages) {
super(null);
- setErrorLevel(ErrorLevel.INFORMATION);
+ setErrorLevel(ErrorLevel.INFO);
for (ErrorMessage errorMessage : errorMessages) {
addErrorMessage(errorMessage);
import java.io.Serializable;
+import com.vaadin.shared.ui.ErrorLevel;
+
/**
* Interface for rendering error messages to terminal. All the visible errors
* shown to user must implement this interface.
*/
public interface ErrorMessage extends Serializable {
- public enum ErrorLevel {
- /**
- * Error code for informational messages.
- */
- INFORMATION("info", 0),
- /**
- * Error code for warning messages.
- */
- WARNING("warning", 1),
- /**
- * Error code for regular error messages.
- */
- ERROR("error", 2),
- /**
- * Error code for critical error messages.
- */
- CRITICAL("critical", 3),
- /**
- * Error code for system errors and bugs.
- */
- SYSTEMERROR("system", 4);
-
- String text;
- int errorLevel;
-
- private ErrorLevel(String text, int errorLevel) {
- this.text = text;
- this.errorLevel = errorLevel;
- }
-
- /**
- * Textual representation for server-client communication of level
- *
- * @return String for error severity
- */
- public String getText() {
- return text;
- }
-
- /**
- * Integer representation of error severity for comparison
- *
- * @return integer for error severity
- */
- public int intValue() {
- return errorLevel;
- }
-
- @Override
- public String toString() {
- return text;
- }
-
- }
-
/**
- * @deprecated As of 7.0, use {@link ErrorLevel#SYSTEMERROR} instead  Â
+ * @deprecated As of 7.0, use {@link ErrorLevel#SYSTEM} instead  Â
*/
@Deprecated
- public static final ErrorLevel SYSTEMERROR = ErrorLevel.SYSTEMERROR;
+ public static final ErrorLevel SYSTEMERROR = ErrorLevel.SYSTEM;
/**
* @deprecated As of 7.0, use {@link ErrorLevel#CRITICAL} instead  Â
public static final ErrorLevel WARNING = ErrorLevel.WARNING;
/**
- * @deprecated As of 7.0, use {@link ErrorLevel#INFORMATION} instead  Â
+ * @deprecated As of 7.0, use {@link ErrorLevel#INFO} instead  Â
*/
@Deprecated
- public static final ErrorLevel INFORMATION = ErrorLevel.INFORMATION;
+ public static final ErrorLevel INFORMATION = ErrorLevel.INFO;
/**
* Gets the errors level.
package com.vaadin.server;
+import com.vaadin.shared.ui.ErrorLevel;
+
/**
* <code>SystemError</code> is an error message for a problem caused by error in
* system, not the user application code. The system error can contain technical
*/
public SystemError(String message) {
super(message);
- setErrorLevel(ErrorLevel.SYSTEMERROR);
+ setErrorLevel(ErrorLevel.SYSTEM);
setMode(ContentMode.HTML);
setMessage(getHtmlMessage());
}
package com.vaadin.server;
+import com.vaadin.shared.ui.ErrorLevel;
+
/**
* <code>UserError</code> is a controlled error occurred in application. User
* errors are occur in normal usage of the application and guide the user.
import com.vaadin.server.ClientConnector;
import com.vaadin.server.ComponentSizeValidator;
import com.vaadin.server.ErrorMessage;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.Extension;
import com.vaadin.server.Resource;
import com.vaadin.server.Responsive;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ComponentStateUtil;
import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
ErrorMessage error = getErrorMessage();
if (null != error) {
getState().errorMessage = error.getFormattedHtmlMessage();
+ getState().errorLevel = error.getErrorLevel();
} else {
getState().errorMessage = null;
+ getState().errorLevel = null;
}
}
public void setComponentError(ErrorMessage componentError) {
this.componentError = componentError;
- String formattedHtmlMessage = componentError != null
- ? componentError.getFormattedHtmlMessage() : null;
- tabState.componentError = formattedHtmlMessage;
+ if (componentError != null) {
+ tabState.componentError = componentError
+ .getFormattedHtmlMessage();
+ tabState.componentErrorLevel = componentError.getErrorLevel();
+ } else {
+ tabState.componentError = null;
+ tabState.componentErrorLevel = null;
+ }
+
markAsDirty();
}
import org.junit.Before;
import org.junit.Test;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.FileResource;
import com.vaadin.server.Responsive;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.UserError;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Button;
import org.junit.Test;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.FileResource;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.UserError;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.tests.design.DeclarativeTestBase;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.SharedState;
import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.shared.ui.ErrorLevel;
/**
* Default shared state implementation for AbstractComponent.
public String id = null;
public String primaryStyleName = null;
- // HTML formatted error message for the component
- // TODO this could be an object with more information, but currently the UI
- // only uses the message
+ /** HTML formatted error message for the component */
public String errorMessage = null;
+
+ /**
+ * Level of error
+ *
+ * @since 8.2
+ */
+ public ErrorLevel errorLevel = null;
+
public boolean captionAsHtml = false;
}
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui;
+
+/**
+ * Represents the error levels displayed on components.
+ * @author Vaadin Ltd
+ * @since
+ */
+public enum ErrorLevel {
+
+ /**
+ * Error level for informational messages.
+ */
+ INFO,
+
+ /**
+ * Error level for warning messages.
+ */
+ WARNING,
+
+ /**
+ * Error level for regular messages.
+ */
+ ERROR,
+
+ /**
+ * Error level for critical messages.
+ */
+ CRITICAL,
+
+ /**
+ * Error level for system errors and bugs.
+ */
+ SYSTEM;
+
+ /**
+ * Integer representation of error severity for comparison
+ *
+ * @return integer for error severity
+ */
+ public int intValue() {
+ return ordinal();
+ }
+}
import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.shared.ui.ErrorLevel;
+
/**
* Shared state of a single tab in a Tabsheet or an Accordion.
*
public String styleName;
public String key;
public String componentError;
+
+ /**
+ * Represents the level of error on a tab.
+ *
+ * @since 8.2
+ */
+ public ErrorLevel componentErrorLevel;
public String id;
public String iconAltText;
-Subproject commit 3a4a26065d36ac5fb706c159f1dd757fb52bf8eb
+Subproject commit 37f67cd836df7d34469f55298bb167696338f2a5
}
}
+ .#{$primary-stylename}-error-info {
+ .#{$primary-stylename}-input {
+ @include valo-textfield-error-level-info-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-info-color;
+ border-color: $v-error-indicator-level-info-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-warning {
+ .#{$primary-stylename}-input {
+ @include valo-textfield-error-level-warning-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-warning-color;
+ border-color: $v-error-indicator-level-warning-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-error {
+ .#{$primary-stylename}-input {
+ @include valo-textfield-error-level-error-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-error-color;
+ border-color: $v-error-indicator-level-error-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-critical {
+ .#{$primary-stylename}-input {
+ @include valo-textfield-error-level-critical-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-critical-color;
+ border-color: $v-error-indicator-level-critical-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-system {
+ .#{$primary-stylename}-input {
+ @include valo-textfield-error-level-system-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-system-color;
+ border-color: $v-error-indicator-level-system-color;
+ }
+ }
+
.#{$primary-stylename}-suggestpopup {
@include valo-combobox-popup-style;
}
}
}
+ .#{$primary-stylename}-error-info {
+ .#{$primary-stylename}-textfield {
+ @include valo-textfield-error-level-info-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-info-color;
+ border-color: $v-error-indicator-level-info-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-warning {
+ .#{$primary-stylename}-textfield {
+ @include valo-textfield-error-level-warning-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-warning-color;
+ border-color: $v-error-indicator-level-warning-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-error {
+ .#{$primary-stylename}-textfield {
+ @include valo-textfield-error-level-error-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-error-color;
+ border-color: $v-error-indicator-level-error-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-critical {
+ .#{$primary-stylename}-textfield {
+ @include valo-textfield-error-level-critical-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-critical-color;
+ border-color: $v-error-indicator-level-critical-color;
+ }
+ }
+
+ .#{$primary-stylename}-error-system {
+ .#{$primary-stylename}-textfield {
+ @include valo-textfield-error-level-system-style;
+ }
+
+ .#{$primary-stylename}-button {
+ color: $v-error-indicator-level-system-color;
+ border-color: $v-error-indicator-level-system-color;
+ }
+ }
+
// Different widths for different resolutions
.#{$primary-stylename}-full {
width: round($v-font-size * 15);
@include valo-textfield-error-style;
}
+ .#{$primary-stylename}-error-info {
+ @include valo-textfield-error-level-info-style;
+ }
+
+ .#{$primary-stylename}-error-warning {
+ @include valo-textfield-error-level-warning-style;
+ }
+
+ .#{$primary-stylename}-error-error {
+ @include valo-textfield-error-level-error-style;
+ }
+
+ .#{$primary-stylename}-error-critical {
+ @include valo-textfield-error-level-critical-style;
+ }
+
+ .#{$primary-stylename}-error-system {
+ @include valo-textfield-error-level-system-style;
+ }
@if $include-additional-styles {
.#{$primary-stylename}-borderless {
*
* @group textfield
*/
-@mixin valo-textfield-error-style {
- border-color: $v-error-indicator-color !important;
- $bg: scale-color($v-error-indicator-color, $lightness: 98%);
+@mixin valo-textfield-error-style($indicator-color: $v-error-indicator-color) {
+ border-color: $indicator-color !important;
+ $bg: scale-color($indicator-color, $lightness: 98%);
background: $bg;
color: valo-font-color($bg);
}
+/**
+ * Outputs the styles for a text field error state with error level 'info'.
+ *
+ * @group textfield
+ */
+@mixin valo-textfield-error-level-info-style {
+ @include valo-textfield-error-style($v-error-indicator-level-info-color);
+}
+
+/**
+ * Outputs the styles for a text field error state with error level 'warning'.
+ *
+ * @group textfield
+ */
+@mixin valo-textfield-error-level-warning-style {
+ @include valo-textfield-error-style($v-error-indicator-level-warning-color);
+}
+
+/**
+ * Outputs the styles for a text field error state with error level 'error'.
+ *
+ * @group textfield
+ */
+@mixin valo-textfield-error-level-error-style {
+ @include valo-textfield-error-style($v-error-indicator-level-error-color);
+}
+
+/**
+ * Outputs the styles for a text field error state with error level 'critical'.
+ *
+ * @group textfield
+ */
+@mixin valo-textfield-error-level-critical-style {
+ @include valo-textfield-error-style($v-error-indicator-level-critical-color);
+}
+
+/**
+ * Outputs the styles for a text field error state with error level 'system'.
+ *
+ * @group textfield
+ */
+@mixin valo-textfield-error-level-system-style {
+ @include valo-textfield-error-style($v-error-indicator-level-system-color);
+}
+
/**
* Outputs the selectors and styles for an inline-icon style for a text field. Included indipendently (i.e. not enclosed with a parent text field selector).
}
}
+ .#{$primary-stylename}-error-info {
+ .#{$primary-stylename}-options,
+ .#{$primary-stylename}-selections {
+ @include valo-textfield-error-level-info-style;
+ }
+ }
+
+ .#{$primary-stylename}-error-warning {
+ .#{$primary-stylename}-options,
+ .#{$primary-stylename}-selections {
+ @include valo-textfield-error-level-warning-style;
+ }
+ }
+
+ .#{$primary-stylename}-error-error {
+ .#{$primary-stylename}-options,
+ .#{$primary-stylename}-selections {
+ @include valo-textfield-error-level-error-style;
+ }
+ }
+
+ .#{$primary-stylename}-error-critical {
+ .#{$primary-stylename}-options,
+ .#{$primary-stylename}-selections {
+ @include valo-textfield-error-level-critical-style;
+ }
+ }
+
+ .#{$primary-stylename}-error-system {
+ .#{$primary-stylename}-options,
+ .#{$primary-stylename}-selections {
+ @include valo-textfield-error-level-system-style;
+ }
+ }
}
@include valo-error-indicator-style;
}
+ .v-errorindicator-info {
+ @include valo-error-indicator-style($indicator-color: $v-error-indicator-level-info-color);
+ }
+
+ .v-errorindicator-warning {
+ @include valo-error-indicator-style($indicator-color: $v-error-indicator-level-warning-color);
+ }
+
+ .v-errorindicator-error {
+ @include valo-error-indicator-style($indicator-color: $v-error-indicator-level-error-color);
+ }
+
+ .v-errorindicator-critical {
+ @include valo-error-indicator-style($indicator-color: $v-error-indicator-level-critical-color);
+ }
+
+ .v-errorindicator-system {
+ @include valo-error-indicator-style($indicator-color: $v-error-indicator-level-system-color);
+ }
+
.v-required-field-indicator {
color: $v-required-field-indicator-color;
padding: 0 .2em;
*
* @requires {mixin} valo-error-indicator-icon-style by default
*/
-@mixin valo-error-indicator-style ($is-pseudo-element: false) {
- color: $v-error-indicator-color;
+@mixin valo-error-indicator-style ($is-pseudo-element: false, $indicator-color: $v-error-indicator-color) {
+ color: $indicator-color;
font-weight: 600;
width: ceil($v-unit-size/2);
text-align: center;
*/
$v-tooltip-error-message-font-color: $v-error-indicator-color !default;
+/**
+ * The font color for error tooltips for level 'info'.
+ *
+ * @type color
+ * @group tooltip
+ */
+$v-tooltip-error-message-level-info-font-color: $v-error-indicator-level-info-color !default;
+
+/**
+ * The font color for error tooltips for level 'warning'.
+ *
+ * @type color
+ * @group tooltip
+ */
+$v-tooltip-error-message-level-warning-font-color: $v-error-indicator-level-warning-color !default;
+
+/**
+ * The font color for error tooltips for level 'error'.
+ *
+ * @type color
+ * @group tooltip
+ */
+$v-tooltip-error-message-level-error-font-color: $v-error-indicator-level-error-color !default;
+
+/**
+ * The font color for error tooltips for level 'critical'.
+ *
+ * @type color
+ * @group tooltip
+ */
+$v-tooltip-error-message-level-critical-font-color: $v-error-indicator-level-critical-color !default;
+
+/**
+ * The font color for error tooltips for level 'system'.
+ *
+ * @type color
+ * @group tooltip
+ */
+$v-tooltip-error-message-level-system-font-color: $v-error-indicator-level-system-color !default;
+
/**
* The corner radius for tooltips.
*
}
}
+ .v-errormessage-info {
+ color: $v-tooltip-error-message-level-info-font-color;
+ }
+
+ .v-errormessage-warning {
+ color: $v-tooltip-error-message-level-warning-font-color;
+ }
+
+ .v-errormessage-error {
+ color: $v-tooltip-error-message-level-error-font-color;
+ }
+
+ .v-errormessage-critical {
+ color: $v-tooltip-error-message-level-critical-font-color;
+ }
+
+ .v-errormessage-system {
+ color: $v-tooltip-error-message-level-system-font-color;
+ }
+
.v-tooltip-text {
max-height: 10em;
overflow: auto;
*/
$v-selection-color: $v-focus-color !default;
+/**
+ * Color of the component error indication for 'info' error level.
+
+ * @group color
+ * @type color
+ */
+$v-error-indicator-level-info-color: #00a7f5 !default;
+
+/**
+ * Color of the component error indication for 'warning' error level.
+
+ * @group color
+ * @type color
+ */
+$v-error-indicator-level-warning-color: #fc9c00 !default;
+
+/**
+ * Color of the component error indication for 'error' error level.
+
+ * @group color
+ * @type color
+ */
+$v-error-indicator-level-error-color: #ed473b !default;
+
+/**
+ * Color of the component error indication for 'critical' error level.
+
+ * @group color
+ * @type color
+ */
+$v-error-indicator-level-critical-color: #fa007d !default;
+
+/**
+ * Color of the component error indication for 'system' error level.
+
+ * @group color
+ * @type color
+ */
+$v-error-indicator-level-system-color: #bb00ff !default;
+
/**
* Color of the component error indicator and other error indications, such as the
* error style notification.
* @group color
* @type color
*/
-$v-error-indicator-color: #ed473b !default;
+$v-error-indicator-color: $v-error-indicator-level-error-color !default;
/**
* Color of the required indicator in field components.
--- /dev/null
+package com.vaadin.tests.components;
+
+import java.util.Arrays;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.AbstractErrorMessage;
+import com.vaadin.server.ErrorMessage;
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.UserError;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.ErrorLevel;
+import com.vaadin.ui.Accordion;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.DateField;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Link;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.TwinColSelect;
+import com.vaadin.ui.themes.ValoTheme;
+
+@Theme("valo")
+public class ErrorLevels extends AbstractTestUI {
+
+ private ComboBox<ErrorLevel> errorLevels;
+ private Button button;
+ private Button borderlessButton;
+ private Link link;
+ private ComboBox<String> comboBox;
+ private TextField textField;
+ private TextField textFieldBorderless;
+ private TabSheet tabSheet;
+ private Accordion accordion;
+ private CheckBox checkBox;
+ private NativeButton nativeButton;
+ private FormLayout formLayout;
+ private TextField formLayoutTextField;
+ private Panel panel;
+ private DateField dateField;
+ private TwinColSelect twinColSelect;
+
+ private com.vaadin.v7.ui.ComboBox comboBoxCompat;
+ private com.vaadin.v7.ui.TextField textFieldCompat;
+ private com.vaadin.v7.ui.CheckBox checkBoxCompat;
+ private com.vaadin.v7.ui.DateField dateFieldCompat;
+ private com.vaadin.v7.ui.TwinColSelect twinColSelectCompat;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ errorLevels = new ComboBox<>("Error level",
+ Arrays.asList(ErrorLevel.values()));
+ errorLevels.setEmptySelectionAllowed(false);
+ errorLevels.setValue(ErrorLevel.ERROR);
+ errorLevels.addValueChangeListener(event -> setErrorMessages());
+ addComponent(errorLevels);
+
+ Label subtitle = new Label("Components");
+ subtitle.setStyleName(ValoTheme.LABEL_H3);
+ addComponent(subtitle);
+
+ // Button
+ button = new Button("Button");
+
+ borderlessButton = new Button("Borderless button");
+ borderlessButton.setStyleName(ValoTheme.BUTTON_BORDERLESS);
+
+ addComponent(new HorizontalLayout(button, borderlessButton));
+
+ // Native button
+ nativeButton = new NativeButton("Native button");
+ addComponent(nativeButton);
+
+ // Link
+ link = new Link("Link", new ExternalResource("#"));
+ addComponent(link);
+
+ // Combo box
+ comboBox = new ComboBox<>("Combo box");
+ addComponent(comboBox);
+
+ // Text field
+ textField = new TextField("Text field");
+ textField.setValue("text");
+
+ textFieldBorderless = new TextField("Borderless text field");
+ textFieldBorderless.setStyleName(ValoTheme.TEXTFIELD_BORDERLESS);
+ textFieldBorderless.setValue("text");
+
+ addComponent(new HorizontalLayout(textField, textFieldBorderless));
+
+ // Date field
+ dateField = new DateField("Date field");
+ addComponent(dateField);
+
+ // Check box
+ checkBox = new CheckBox("Check box");
+ addComponent(checkBox);
+
+ // Tab sheet
+ tabSheet = new TabSheet();
+ tabSheet.addTab(new Label("Label1"), "Tab1");
+ tabSheet.addTab(new Label("Label2"), "Tab2");
+ tabSheet.setWidth("400px");
+ addComponent(tabSheet);
+
+ // Accordion
+ accordion = new Accordion();
+ accordion.addTab(new Label("Label1"), "Tab1");
+ accordion.addTab(new Label("Label2"), "Tab2");
+ accordion.setWidth("400px");
+ addComponent(accordion);
+
+ // Form layout
+ formLayout = new FormLayout();
+ formLayout.setWidth("400px");
+
+ formLayoutTextField = new TextField("Form layout text field");
+ formLayout.addComponent(formLayoutTextField);
+
+ addComponent(formLayout);
+
+ // Panel
+ panel = new Panel();
+ panel.setContent(new Label("Panel"));
+ panel.setWidth("400px");
+ addComponent(panel);
+
+ // TwinColSelect
+ twinColSelect = new TwinColSelect("Twin col select");
+ addComponent(twinColSelect);
+
+ Label subtitleCompat = new Label("Compatibility components");
+ subtitleCompat.setStyleName(ValoTheme.LABEL_H3);
+ addComponent(subtitleCompat);
+
+ // Compatibility combo box
+ comboBoxCompat = new com.vaadin.v7.ui.ComboBox(
+ "Compatibility combo box");
+ addComponent(comboBoxCompat);
+
+ // Compatibility text field
+ textFieldCompat = new com.vaadin.v7.ui.TextField(
+ "Compatibility text field");
+ textFieldCompat.setValue("text");
+
+ // Compatibility check box
+ checkBoxCompat = new com.vaadin.v7.ui.CheckBox("Check box");
+ addComponent(checkBoxCompat);
+
+ // Compatibility date field
+ dateFieldCompat = new com.vaadin.v7.ui.DateField("Date field");
+ addComponent(dateFieldCompat);
+
+ // Compatibility twin col select
+ twinColSelectCompat = new com.vaadin.v7.ui.TwinColSelect(
+ "Twin col select");
+ addComponent(twinColSelectCompat);
+
+ setErrorMessages();
+
+ getLayout().setSpacing(true);
+ }
+
+ private void setErrorMessages() {
+ button.setComponentError(createErrorMessage("Button error"));
+ borderlessButton.setComponentError(
+ createErrorMessage("Borderless button error"));
+ link.setComponentError(createErrorMessage("Link error"));
+ comboBox.setComponentError(createErrorMessage("ComboBox error"));
+ textField.setComponentError(createErrorMessage("Text field error"));
+ textFieldBorderless.setComponentError(
+ createErrorMessage("Borderless text field error"));
+ tabSheet.setComponentError(createErrorMessage("Tab sheet error"));
+ tabSheet.getTab(0).setComponentError(createErrorMessage("Tab error"));
+ accordion.setComponentError(createErrorMessage("Accordion error"));
+ accordion.getTab(0).setComponentError(createErrorMessage("Tab error"));
+ checkBox.setComponentError(createErrorMessage("Check box error"));
+ nativeButton
+ .setComponentError(createErrorMessage("Native button error"));
+ formLayout.setComponentError(createErrorMessage("Form layout error"));
+ formLayoutTextField.setComponentError(
+ createErrorMessage("Form layout text field error"));
+ panel.setComponentError(createErrorMessage("Panel error"));
+ dateField.setComponentError(createErrorMessage("Date field error"));
+ twinColSelect
+ .setComponentError(createErrorMessage("Twin col select error"));
+ comboBoxCompat.setComponentError(
+ createErrorMessage("Compatibility combo box error"));
+ textFieldCompat.setComponentError(
+ createErrorMessage("Compatibility text field error"));
+ checkBoxCompat.setComponentError(
+ createErrorMessage("Compatibility check box error"));
+ dateFieldCompat.setComponentError(
+ createErrorMessage("Compatibility date field error"));
+ twinColSelectCompat.setComponentError(
+ createErrorMessage("Compatibility twin col select error"));
+ }
+
+ private ErrorMessage createErrorMessage(String text) {
+ return new UserError(text, AbstractErrorMessage.ContentMode.TEXT,
+ errorLevels.getValue());
+ }
+}
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.AbstractErrorMessage;
-import com.vaadin.server.ErrorMessage.ErrorLevel;
import com.vaadin.server.Page;
import com.vaadin.server.UserError;
import com.vaadin.shared.Position;
import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
--- /dev/null
+package com.vaadin.tests.components;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.client.StyleConstants;
+import com.vaadin.shared.ui.ErrorLevel;
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.AccordionElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.CheckBoxElement;
+import com.vaadin.testbench.elements.ComboBoxElement;
+import com.vaadin.testbench.elements.DateFieldElement;
+import com.vaadin.testbench.elements.FormLayoutElement;
+import com.vaadin.testbench.elements.LinkElement;
+import com.vaadin.testbench.elements.NativeButtonElement;
+import com.vaadin.testbench.elements.PanelElement;
+import com.vaadin.testbench.elements.TabSheetElement;
+import com.vaadin.testbench.elements.TwinColSelectElement;
+import com.vaadin.testbench.parallel.BrowserUtil;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class ErrorLevelsTest extends SingleBrowserTest {
+
+ private ComboBoxElement errorLevelSelector;
+
+ @Override
+ public void setup() throws Exception {
+ super.setup();
+ openTestURL();
+
+ errorLevelSelector = $(ComboBoxElement.class).first();
+ }
+
+ @Test
+ public void testErrorIndicatorsClassName() {
+ ErrorLevel errorLevel = ErrorLevel.WARNING;
+ selectErrorLevel(errorLevel);
+
+ List<WebElement> errorIndicators = findElements(
+ By.className(StyleConstants.STYLE_NAME_ERROR_INDICATOR));
+ for (WebElement errorIndicator : errorIndicators) {
+ assertHasRightClassNames(errorIndicator,
+ StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel);
+ }
+ }
+
+ @Test
+ public void testComponentsClassName() {
+ ErrorLevel errorLevel = ErrorLevel.WARNING;
+ selectErrorLevel(errorLevel);
+
+ // Button
+ ButtonElement buttonElement = $(ButtonElement.class).first();
+ assertHasRightClassNames(buttonElement, "v-button-error", errorLevel);
+
+ // Native button
+ NativeButtonElement nativeButtonElement = $(NativeButtonElement.class)
+ .first();
+ assertHasRightClassNames(nativeButtonElement, "v-nativebutton-error",
+ errorLevel);
+
+ // Link
+ LinkElement linkElement = $(LinkElement.class).first();
+ assertHasRightClassNames(linkElement, "v-link-error", errorLevel);
+
+ // Combo box
+ ComboBoxElement comboBoxElement = $(ComboBoxElement.class).get(1);
+ assertHasRightClassNames(comboBoxElement, "v-filterselect-error",
+ errorLevel);
+
+ // Date field
+ DateFieldElement dateFieldElement = $(DateFieldElement.class).first();
+ assertHasRightClassNames(dateFieldElement, "v-datefield-error",
+ errorLevel);
+
+ // Checkbox
+ CheckBoxElement checkBoxElement = $(CheckBoxElement.class).first();
+ assertHasRightClassNames(checkBoxElement, "v-checkbox-error",
+ errorLevel);
+
+ // Tab sheet
+ TabSheetElement tabSheetElement = $(TabSheetElement.class).first();
+ assertHasRightClassNames(tabSheetElement, "v-tabsheet-error",
+ errorLevel);
+
+ // Accordion
+ AccordionElement accordionElement = $(AccordionElement.class).first();
+ assertHasRightClassNames(accordionElement, "v-accordion-error",
+ errorLevel);
+
+ // Form layout
+ FormLayoutElement formLayoutElement = $(FormLayoutElement.class)
+ .first();
+ assertHasRightClassNames(formLayoutElement, "v-formlayout-error",
+ errorLevel);
+
+ // Panel
+ PanelElement panelElement = $(PanelElement.class).first();
+ assertHasRightClassNames(panelElement, "v-panel-error", errorLevel);
+
+ // Twin col select
+ TwinColSelectElement twinColSelectElement = $(
+ TwinColSelectElement.class).first();
+ assertHasRightClassNames(twinColSelectElement, "v-select-twincol-error",
+ errorLevel);
+ }
+
+ private void assertHasRightClassNames(WebElement element, String prefix,
+ ErrorLevel errorLevel) {
+ Assert.assertTrue("Element must have only one error level class name",
+ containsCorrectErrorLevelClassNameOnly(element, prefix,
+ errorLevel));
+ }
+
+ private boolean containsCorrectErrorLevelClassNameOnly(WebElement element,
+ String prefix, ErrorLevel errorLevel) {
+ List<String> classNames = new ArrayList<String>(
+ Arrays.asList(element.getAttribute("class").split(" ")));
+ classNames.retainAll(getErrorLevelClassNames(prefix,
+ Arrays.asList(ErrorLevel.values())));
+ return classNames.size() == 1 && classNames
+ .contains(getErrorLevelClassName(prefix, errorLevel));
+ }
+
+ private String getErrorLevelClassName(String prefix,
+ ErrorLevel errorLevel) {
+ return prefix + "-" + errorLevel.toString().toLowerCase();
+ }
+
+ private List<String> getErrorLevelClassNames(String prefix,
+ Collection<ErrorLevel> errorLevels) {
+ List<String> classNames = new ArrayList<String>(errorLevels.size());
+ for (ErrorLevel errorLevel : errorLevels) {
+ classNames.add(getErrorLevelClassName(prefix, errorLevel));
+ }
+ return classNames;
+ }
+
+ private void selectErrorLevel(ErrorLevel errorLevel) {
+ errorLevelSelector.clear();
+ errorLevelSelector.sendKeys(errorLevel.toString().toLowerCase());
+ errorLevelSelector.sendKeys(getReturn());
+ }
+
+ private Keys getReturn() {
+ if (BrowserUtil.isPhantomJS(getDesiredCapabilities())) {
+ return Keys.ENTER;
+ } else {
+ return Keys.RETURN;
+ }
+ }
+}
}
private WebElement getCurrentErrorMessage() {
- return getDriver()
- .findElement(By.xpath("//div[@class='v-errormessage']"));
+ return getDriver().findElement(
+ By.xpath("//div[contains(@class, 'v-errormessage')]"));
}
private void assertTooltip(String tooltip) {