]> source.dussan.org Git - vaadin-framework.git/commitdiff
DateField not to fire focus/blur event when going to sub-components (#10246)
authorAhmed Ashour <asashour@yahoo.com>
Thu, 23 Nov 2017 05:54:27 +0000 (06:54 +0100)
committercaalador <mikael.grankvist@gmail.com>
Thu, 23 Nov 2017 05:54:27 +0000 (07:54 +0200)
Fixes `DateField blur event fires when focus gets to the "calendar button"` #1008

client/src/main/java/com/vaadin/client/ui/VAbstractCalendarPanel.java
client/src/main/java/com/vaadin/client/ui/VAbstractPopupCalendar.java
client/src/main/java/com/vaadin/client/ui/VAbstractTextualDate.java
uitest/src/main/java/com/vaadin/tests/components/FocusAndBlurListeners.java
uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldFocus.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldFocusTest.java [new file with mode: 0644]

index 70bec08e4fbd90862baf3d454ae92ac7f93a177d..f009f483e04c1d70d386c70608568aa5533454a3 100644 (file)
@@ -1997,7 +1997,6 @@ public abstract class VAbstractCalendarPanel<R extends Enum<R>>
                 renderCalendar();
             }
         }
-
     }
 
     /**
index d894653609b1e06287ef9b6becd65ac1dded54db..4df4d0e3257608806b758934eff15852390aad9f 100644 (file)
@@ -377,7 +377,6 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane
      * Opens the calendar panel popup.
      */
     public void openCalendarPanel() {
-
         if (!open && !readonly && isEnabled()) {
             open = true;
 
@@ -393,6 +392,8 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane
             popup.setWidth("");
             popup.setHeight("");
             popup.setPopupPositionAndShow(new PopupPositionCallback());
+
+            checkGroupFocus(true);
         } else {
             getLogger().severe("Cannot reopen popup, it is already open!");
         }
@@ -451,6 +452,7 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane
      * Sets focus to Calendar panel.
      *
      * @param focus
+     *            {@code true} for {@code focus}, {@code false} for {@code blur}
      */
     public void setFocus(boolean focus) {
         calendar.setFocus(focus);
@@ -683,19 +685,16 @@ public abstract class VAbstractPopupCalendar<PANEL extends VAbstractCalendarPane
                 // are in the lower right corner of the screen
                 if (overflow) {
                     return left;
-                } else {
-                    return left + calendarToggle.getOffsetWidth();
-                }
-            } else {
-                int[] margins = style.getMargin();
-                int desiredLeftPosition = calendarToggle.getAbsoluteLeft()
-                        - width - margins[1] - margins[3];
-                if (desiredLeftPosition >= 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<PANEL extends VAbstractCalendarPane
         }
     }
 
+    @Override
+    protected boolean hasChildFocus() {
+        return open;
+    }
+
     private static Logger getLogger() {
         return Logger.getLogger(VAbstractPopupCalendar.class.getName());
     }
index 66ddf1d829e4237a58b11e836a02aec69833a7ca..11102a218e6e5d5cec23af49fc0ab720374ee7f3 100644 (file)
@@ -21,6 +21,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.google.gwt.aria.client.Roles;
+import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
@@ -76,14 +77,19 @@ public abstract class VAbstractTextualDate<R extends Enum<R>>
     /** 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<R extends Enum<R>>
     }
 
     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<R extends Enum<R>>
     private static Logger getLogger() {
         return Logger.getLogger(VAbstractTextualDate.class.getName());
     }
+
 }
index b1e5f2ef59e71da570bb762a3bc875c44de3b7b7..d34eadf7f69e027e643348ac9208bc06342623e2 100644 (file)
@@ -43,7 +43,7 @@ public class FocusAndBlurListeners extends TestBase {
         AbstractDateField<?, ?> df = new TestDateField("DateField");
         l.addComponent(df);
 
-        ComboBox cb = new ComboBox("ComboBox");
+        ComboBox<String> 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 (file)
index 0000000..2edfa0a
--- /dev/null
@@ -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 (file)
index 0000000..423ff2e
--- /dev/null
@@ -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)));
+    }
+}