From 8a264ec4052cbee467269824e6e9e7c76efd1d07 Mon Sep 17 00:00:00 2001 From: Mikael Grankvist Date: Mon, 17 Dec 2012 08:35:53 +0200 Subject: [PATCH] (#9949) Flush focused connector on historyChange Change-Id: Ia0f41220a038a83fcbcbbe9feebe066cbc626e27 --- .../vaadin/client/ApplicationConnection.java | 26 ++++ .../com/vaadin/client/ComponentConnector.java | 12 ++ client/src/com/vaadin/client/Util.java | 17 ++- .../client/ui/AbstractComponentConnector.java | 9 ++ client/src/com/vaadin/client/ui/VUI.java | 2 + .../richtextarea/RichTextAreaConnector.java | 7 +- .../ui/textfield/TextFieldConnector.java | 5 + .../components/uitest/BackButtonTest.java | 117 ++++++++++++++++++ 8 files changed, 191 insertions(+), 4 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/uitest/BackButtonTest.java diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 2e8387c5da..4a625383a5 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -3271,4 +3271,30 @@ public class ApplicationConnection { GwtEvent.Type type, H handler) { return eventBus.addHandler(type, handler); } + + /** + * Calls {@link ComponentConnector#flush()} on the active connector. Does + * nothing if there is no active (focused) connector. + */ + public void flushActiveConnector() { + ComponentConnector activeConnector = getActiveConnector(); + if (activeConnector == null) { + return; + } + activeConnector.flush(); + } + + /** + * Gets the active connector for focused element in browser. + * + * @return Connector for focused element or null. + */ + private ComponentConnector getActiveConnector() { + Element focusedElement = Util.getFocusedElement(); + if (focusedElement == null) { + return null; + } + return Util.getConnectorForElement(this, getUIConnector().getWidget(), + focusedElement); + } } diff --git a/client/src/com/vaadin/client/ComponentConnector.java b/client/src/com/vaadin/client/ComponentConnector.java index 63e55153b6..db3cc25c56 100644 --- a/client/src/com/vaadin/client/ComponentConnector.java +++ b/client/src/com/vaadin/client/ComponentConnector.java @@ -127,4 +127,16 @@ public interface ComponentConnector extends ServerConnector { */ public TooltipInfo getTooltipInfo(Element element); + /** + * Called for the active (focused) connector when a situation occurs that + * the focused connector might have buffered changes which need to be + * processed before other activity takes place. + *

+ * This is currently called when the user changes the fragment using the + * back/forward button in the browser and allows the focused field to submit + * its value to the server before the fragment change event takes place. + *

+ */ + public void flush(); + } diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index 0df8bfb90f..3d6f64d4d5 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -1059,11 +1059,11 @@ public class Util { } /** - * Gets the currently focused element for Internet Explorer. + * Gets the currently focused element. * - * @return The currently focused element + * @return The active element or null if no active element could be found. */ - public native static Element getIEFocusedElement() + public native static Element getFocusedElement() /*-{ if ($wnd.document.activeElement) { return $wnd.document.activeElement; @@ -1072,6 +1072,17 @@ public class Util { return null; }-*/ ; + + /** + * Gets the currently focused element for Internet Explorer. + * + * @return The currently focused element + * @deprecated Use #getFocusedElement instead + */ + @Deprecated + public static Element getIEFocusedElement() { + return getFocusedElement(); + } /** * Kind of stronger version of isAttached(). In addition to std isAttached, diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index f8088d63a2..2c599743e4 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -426,4 +426,13 @@ public abstract class AbstractComponentConnector extends AbstractConnector protected String getIcon() { return getResourceUrl(ComponentConstants.ICON_RESOURCE); } + + /* + * (non-Javadoc) + * + * @see com.vaadin.client.ComponentConnector#flush() + */ + public void flush() { + // No generic implementation. Override if needed + } } diff --git a/client/src/com/vaadin/client/ui/VUI.java b/client/src/com/vaadin/client/ui/VUI.java index cbfbda813e..a21397c060 100644 --- a/client/src/com/vaadin/client/ui/VUI.java +++ b/client/src/com/vaadin/client/ui/VUI.java @@ -129,8 +129,10 @@ public class VUI extends SimplePanel implements ResizeHandler, String newFragment = event.getValue(); // Send the location to the server if the fragment has changed + // and flush active connectors in UI. if (!newFragment.equals(currentFragment) && connection != null) { currentFragment = newFragment; + connection.flushActiveConnector(); connection.updateVariable(id, UIConstants.LOCATION_VARIABLE, Window.Location.getHref(), true); } diff --git a/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java b/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java index afcf479499..8875fc421b 100644 --- a/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java +++ b/client/src/com/vaadin/client/ui/richtextarea/RichTextAreaConnector.java @@ -75,12 +75,17 @@ public class RichTextAreaConnector extends AbstractFieldConnector implements @Override public void onBeforeShortcutAction(Event e) { - getWidget().synchronizeContentToServer(); + flush(); } @Override public VRichTextArea getWidget() { return (VRichTextArea) super.getWidget(); + } + + @Override + public void flush() { + getWidget().synchronizeContentToServer(); }; } diff --git a/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java b/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java index c653b06cf9..bedcd5f936 100644 --- a/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java +++ b/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java @@ -114,6 +114,11 @@ public class TextFieldConnector extends AbstractFieldConnector implements @Override public void onBeforeShortcutAction(Event e) { + flush(); + } + + @Override + public void flush() { getWidget().valueChange(false); } diff --git a/uitest/src/com/vaadin/tests/components/uitest/BackButtonTest.java b/uitest/src/com/vaadin/tests/components/uitest/BackButtonTest.java new file mode 100644 index 0000000000..d5bac0d509 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/uitest/BackButtonTest.java @@ -0,0 +1,117 @@ +package com.vaadin.tests.components.uitest; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.Page.UriFragmentChangedEvent; +import com.vaadin.server.Page.UriFragmentChangedListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Label; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; + +public class BackButtonTest extends AbstractTestUI { + + private VerticalLayout layout; + + private String value = "Hello"; + private Page1 p1; + private Page2 p2; + + @Override + public void setup(VaadinRequest request) { + getPage().setUriFragment("page1"); + + layout = new VerticalLayout(); + addComponent(layout); + + p1 = new Page1(); + addComponent(p1); + + p2 = new Page2(); + getPage().addUriFragmentChangedListener( + new UriFragmentChangedListener() { + + @Override + public void uriFragmentChanged(UriFragmentChangedEvent event) { + String f = event.getUriFragment(); + if ("page2".equals(f)) { + showPage2(); + } + + if ("page1".equals(f)) { + showPage1(); + } + } + }); + } + + class Page1 extends VerticalLayout { + Label l = new Label(); + + public Page1() { + setSizeFull(); + l.setCaption("Data from Page 1 : " + value); + addComponent(l); + + Button b = new Button("Go to Page 2", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + l.setCaption("Data from Page 1 : " + value); + getPage().setUriFragment("page2"); + } + }); + addComponent(b); + } + } + + private void showPage2() { + removeComponent(p1); + p2.f.setValue(""); + addComponent(p2); + } + + private void showPage1() { + removeComponent(p2); + addComponent(p1); + } + + class Page2 extends VerticalLayout { + private final TextField f = new TextField(); + + public Page2() { + setSizeFull(); + + addComponent(f); + f.addValueChangeListener(new ValueChangeListener() { + public void valueChange(ValueChangeEvent event) { + value = f.getValue(); + p1.l.setCaption("Data from Page 2 : " + value); + } + }); + + Button b = new Button("Go Back", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + getPage().setUriFragment("page1"); + } + }); + addComponent(b); + addComponent(new Label( + "Go back with the back button without creating a blur event on the text field. Text should transfer to page1 label.")); + } + + } + + @Override + protected Integer getTicketNumber() { + return 9949; + } + + @Override + protected String getTestDescription() { + // TODO Auto-generated method stub + return null; + } + +} -- 2.39.5