From: Ahmed Ashour Date: Thu, 23 Nov 2017 05:54:27 +0000 (+0100) Subject: DateField not to fire focus/blur event when going to sub-components (#10246) X-Git-Tag: 8.3.0.alpha1~33 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=acfd75ee2ec8ad97f8dd54e2ae454257e7284159;p=vaadin-framework.git DateField not to fire focus/blur event when going to sub-components (#10246) Fixes `DateField blur event fires when focus gets to the "calendar button"` #1008 --- diff --git a/client/src/main/java/com/vaadin/client/ui/VAbstractCalendarPanel.java b/client/src/main/java/com/vaadin/client/ui/VAbstractCalendarPanel.java index 70bec08e4f..f009f483e0 100644 --- a/client/src/main/java/com/vaadin/client/ui/VAbstractCalendarPanel.java +++ b/client/src/main/java/com/vaadin/client/ui/VAbstractCalendarPanel.java @@ -1997,7 +1997,6 @@ public abstract class VAbstractCalendarPanel> renderCalendar(); } } - } /** diff --git a/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java b/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java index d894653609..4df4d0e325 100644 --- a/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java +++ b/client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java @@ -377,7 +377,6 @@ public abstract class VAbstractPopupCalendar= 0) { - return desiredLeftPosition; - } else { - return left; } + return left + calendarToggle.getOffsetWidth(); } + int[] margins = style.getMargin(); + int desiredLeftPosition = calendarToggle.getAbsoluteLeft() - width + - margins[1] - margins[3]; + if (desiredLeftPosition >= 0) { + return desiredLeftPosition; + } + return left; } private boolean positionRightSide() { @@ -721,6 +720,11 @@ public abstract class VAbstractPopupCalendar> /** For internal use only. May be removed or replaced in the future. */ private TimeZone timeZone; + /** + * Specifies whether the group of components has focus or not. + */ + private boolean groupFocus; + public VAbstractTextualDate(R resoluton) { super(resoluton); text = new TextBox(); text.addChangeHandler(this); text.addFocusHandler( - event -> fireBlurFocusEvent(event, true, EventId.FOCUS)); + event -> fireBlurFocusEvent(event, true)); text.addBlurHandler( - event -> fireBlurFocusEvent(event, false, EventId.BLUR)); + event -> fireBlurFocusEvent(event, false)); if (BrowserInfo.get().isIE()) { addDomHandler(this, KeyDownEvent.getType()); } @@ -394,27 +400,54 @@ public abstract class VAbstractTextualDate> } private void fireBlurFocusEvent(DomEvent event, - boolean addFocusStyleName, String eventId) { + boolean focus) { String styleName = VTextField.CLASSNAME + "-" + VTextField.CLASSNAME_FOCUS; - if (addFocusStyleName) { + if (focus) { text.addStyleName(styleName); } else { text.removeStyleName(styleName); } - if (getClient() != null && connector.hasEventListener(eventId)) { - // may excessively send events if if focus went to another - // sub-component - if (EventId.FOCUS.equals(eventId)) { + + Scheduler.get().scheduleDeferred(() -> checkGroupFocus(focus)); + + // Needed for tooltip event handling + fireEvent(event); + } + + /** + * Checks if the group focus has changed, and sends to the server if needed. + * + * @param textFocus + * the focus of the {@link #text} + * @since + */ + protected void checkGroupFocus(boolean textFocus) { + boolean newGroupFocus = textFocus | hasChildFocus(); + if (getClient() != null + && connector.hasEventListener( + textFocus ? EventId.FOCUS : EventId.BLUR) + && groupFocus != newGroupFocus) { + + if (newGroupFocus) { rpc.focus(); } else { rpc.blur(); } sendBufferedValues(); + groupFocus = newGroupFocus; } + } - // Needed for tooltip event handling - fireEvent(event); + /** + * Returns whether any of the child components has focus. + * + * @return {@code true} if any of the child component has focus, + * {@code false} otherwise + * @since + */ + protected boolean hasChildFocus() { + return false; } /** @@ -479,4 +512,5 @@ public abstract class VAbstractTextualDate> private static Logger getLogger() { return Logger.getLogger(VAbstractTextualDate.class.getName()); } + } diff --git a/uitest/src/main/java/com/vaadin/tests/components/FocusAndBlurListeners.java b/uitest/src/main/java/com/vaadin/tests/components/FocusAndBlurListeners.java index b1e5f2ef59..d34eadf7f6 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/FocusAndBlurListeners.java +++ b/uitest/src/main/java/com/vaadin/tests/components/FocusAndBlurListeners.java @@ -43,7 +43,7 @@ public class FocusAndBlurListeners extends TestBase { AbstractDateField df = new TestDateField("DateField"); l.addComponent(df); - ComboBox cb = new ComboBox("ComboBox"); + ComboBox cb = new ComboBox<>("ComboBox"); l.addComponent(cb); Button btn = new Button("Button"); @@ -91,7 +91,6 @@ public class FocusAndBlurListeners extends TestBase { ogm.addBlurListener(blurListener); l.addComponent(messages); - } private OptionGroup createOptionGroup(String caption) { diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldFocus.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldFocus.java new file mode 100644 index 0000000000..2edfa0ab9f --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldFocus.java @@ -0,0 +1,47 @@ +/* + * 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.tests.components.datefield; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.DateField; +import com.vaadin.ui.TextField; + +public class DateFieldFocus extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + DateField dateField = new DateField(); + dateField.addFocusListener(e -> log("focused")); + dateField.addBlurListener(e -> log("blurred")); + addComponent(dateField); + + TextField textField = new TextField(); + textField.setCaption("second"); + addComponent(textField); + } + + @Override + protected String getTestDescription() { + return "DateField should not trigger events when nagivating between sub-components."; + } + + @Override + protected Integer getTicketNumber() { + return 1008; + } + +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldFocusTest.java b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldFocusTest.java new file mode 100644 index 0000000000..423ff2e71c --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldFocusTest.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.components.datefield; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.testbench.elements.DateFieldElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class DateFieldFocusTest extends MultiBrowserTest { + + @Test + public void focus() { + openTestURL(); + + assertEquals(" ", getLogRow(0)); + DateFieldElement dateField = $(DateFieldElement.class).first(); + TextFieldElement textField = $(TextFieldElement.class).caption("second") + .first(); + + dateField.openPopup(); + dateField.openPopup(); + + dateField.openPopup(); + dateField.openPopup(); + + assertEquals("1. focused", getLogRow(0)); + + textField.focus(); + + waitUntil(input -> "2. blurred".equals(getLogRow(0))); + } +}