Fixes #10854tags/8.10.0.beta1
target = Util.findPaintable(client, et); | target = Util.findPaintable(client, et); | ||||
} | } | ||||
final ComponentConnector finalTarget = target; | final ComponentConnector finalTarget = target; | ||||
event.preventDefault(); | event.preventDefault(); | ||||
/* | /* | ||||
* The focused component might have unpublished changes, try to | * The focused component might have unpublished changes, try to | ||||
* synchronize them before firing shortcut action. | * synchronize them before firing shortcut action. | ||||
*/ | */ | ||||
client.flushActiveConnector(); | client.flushActiveConnector(); | ||||
/* | |||||
* Legacy components don't have built-in logic for flushing, they need a | |||||
* workaround with blur and focus to trigger the value change. | |||||
*/ | |||||
ComponentConnector activeConnector = getActiveConnector(client); | |||||
if (activeConnector != null) { | |||||
Class<?> clz = activeConnector.getClass(); | |||||
while (clz != null) { | |||||
if (clz.getName().equals( | |||||
"com.vaadin.v7.client.ui.AbstractLegacyComponentConnector")) { | |||||
shakeTarget(et); | |||||
Scheduler.get().scheduleDeferred(() -> { | |||||
shakeTarget(et); | |||||
}); | |||||
break; | |||||
} | |||||
clz = clz.getSuperclass(); | |||||
} | |||||
} | |||||
Scheduler.get().scheduleDeferred(() -> { | Scheduler.get().scheduleDeferred(() -> { | ||||
if (finalTarget != null) { | if (finalTarget != null) { | ||||
client.updateVariable(paintableId, "actiontarget", finalTarget, | client.updateVariable(paintableId, "actiontarget", finalTarget, | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* We try to fire value change in the component the key combination was | |||||
* typed. E.g. TextField may contain newly typed text that is expected to be | |||||
* sent to server before the shortcut action is triggered. This is done by | |||||
* removing focus and then returning it immediately back to target element. | |||||
* <p> | |||||
* This is a hack copied over from V7 in order to keep the compatibility | |||||
* classes working. Main V8 classes don't require shaking. | |||||
*/ | |||||
private static void shakeTarget(final Element e) { | |||||
blur(e); | |||||
focus(e); | |||||
} | |||||
private static native ComponentConnector getActiveConnector( | |||||
ApplicationConnection ac) | |||||
/*-{ | |||||
return ac.@com.vaadin.client.ApplicationConnection::getActiveConnector()(); | |||||
}-*/; | |||||
private static native void blur(Element e) | private static native void blur(Element e) | ||||
/*-{ | /*-{ | ||||
if (e.blur) { | if (e.blur) { |
package com.vaadin.tests.components.datefield; | |||||
import java.text.SimpleDateFormat; | |||||
import java.util.Date; | |||||
import com.vaadin.event.ShortcutAction.KeyCode; | |||||
import com.vaadin.event.ShortcutListener; | |||||
import com.vaadin.server.VaadinRequest; | |||||
import com.vaadin.tests.components.AbstractTestUI; | |||||
import com.vaadin.ui.Notification; | |||||
import com.vaadin.v7.ui.DateField; | |||||
@SuppressWarnings("deprecation") | |||||
public class CompatibilityDateFieldShortcut extends AbstractTestUI { | |||||
@Override | |||||
protected void setup(VaadinRequest request) { | |||||
String dateFormat = "dd/MM/yyyy"; | |||||
DateField dateField = new DateField(); | |||||
dateField.setValue(new Date(2018 - 1900, 0, 11)); | |||||
dateField.setDateFormat(dateFormat); | |||||
dateField.addShortcutListener( | |||||
new ShortcutListener("Enter", KeyCode.ENTER, null) { | |||||
@Override | |||||
public void handleAction(Object sender, Object target) { | |||||
SimpleDateFormat df = new SimpleDateFormat(dateFormat); | |||||
Notification.show(df.format(dateField.getValue())); | |||||
} | |||||
}); | |||||
addComponent(dateField); | |||||
} | |||||
@Override | |||||
protected String getTestDescription() { | |||||
return "Modify the date manually (without using the popup element) and" | |||||
+ " then press Enter. The notification should show the modified" | |||||
+ " value instead of the old value."; | |||||
} | |||||
@Override | |||||
protected Integer getTicketNumber() { | |||||
return 10854; | |||||
} | |||||
} |
package com.vaadin.tests.components.datefield; | |||||
import static org.junit.Assert.assertEquals; | |||||
import org.junit.Test; | |||||
import org.openqa.selenium.By; | |||||
import org.openqa.selenium.Keys; | |||||
import org.openqa.selenium.WebElement; | |||||
import com.vaadin.testbench.elements.DateFieldElement; | |||||
import com.vaadin.testbench.elements.NotificationElement; | |||||
import com.vaadin.tests.tb3.SingleBrowserTest; | |||||
public class CompatibilityDateFieldShortcutTest extends SingleBrowserTest { | |||||
private static final String DATEFIELD_VALUE_ORIGINAL = "11/01/2018"; | |||||
private static final String DATEFIELD_VALUE_MODIFIED = "21/01/2018"; | |||||
@Test | |||||
public void modifyValueAndPressEnter() { | |||||
openTestURL(); | |||||
DateFieldElement dateField = $(DateFieldElement.class).first(); | |||||
WebElement dateFieldText = dateField.findElement(By.tagName("input")); | |||||
assertEquals("DateField value should be \"" + DATEFIELD_VALUE_ORIGINAL | |||||
+ "\"", DATEFIELD_VALUE_ORIGINAL, dateField.getValue()); | |||||
dateFieldText.click(); | |||||
dateFieldText.sendKeys(Keys.HOME, Keys.DELETE, "2"); | |||||
dateFieldText.sendKeys(Keys.ENTER); | |||||
assertEquals("DateField value should be \"" + DATEFIELD_VALUE_MODIFIED | |||||
+ "\"", DATEFIELD_VALUE_MODIFIED, dateField.getValue()); | |||||
assertEquals(DATEFIELD_VALUE_MODIFIED, | |||||
$(NotificationElement.class).first().getCaption()); | |||||
} | |||||
} |