diff options
3 files changed, 245 insertions, 0 deletions
diff --git a/client/src/com/vaadin/client/ui/VTextArea.java b/client/src/com/vaadin/client/ui/VTextArea.java index 5150ab2544..e6a3aa2a09 100644 --- a/client/src/com/vaadin/client/ui/VTextArea.java +++ b/client/src/com/vaadin/client/ui/VTextArea.java @@ -23,7 +23,9 @@ import com.google.gwt.dom.client.Style.WhiteSpace; import com.google.gwt.dom.client.TextAreaElement; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; +import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Command; @@ -43,14 +45,21 @@ import com.vaadin.client.ui.dd.VDragCloneAware; * */ public class VTextArea extends VTextField implements VDragCloneAware { + public static final String CLASSNAME = "v-textarea"; private boolean wordwrap = true; private MaxLengthHandler maxLengthHandler = new MaxLengthHandler(); private boolean browserSupportsMaxLengthAttribute = browserSupportsMaxLengthAttribute(); + private EnterDownHandler enterDownHandler = new EnterDownHandler(); public VTextArea() { super(DOM.createTextArea()); setStyleName(CLASSNAME); + + // KeyDownHandler is needed for correct text input on all + // browsers, not just those that don't support a max length attribute + addKeyDownHandler(enterDownHandler); + if (!browserSupportsMaxLengthAttribute) { addKeyUpHandler(maxLengthHandler); addChangeHandler(maxLengthHandler); @@ -249,6 +258,20 @@ public class VTextArea extends VTextField implements VDragCloneAware { } } + private class EnterDownHandler implements KeyDownHandler { + + @Override + public void onKeyDown(KeyDownEvent event) { + // Fix for #12424 - if the key being pressed is enter, we stop + // propagation of the KeyDownEvents. This prevents shortcuts that + // are bound to the enter key from being processed. + if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { + event.stopPropagation(); + } + } + + } + @Override public int getCursorPos() { // This is needed so that TextBoxImplIE6 is used to return the correct @@ -294,6 +317,7 @@ public class VTextArea extends VTextField implements VDragCloneAware { // Overridden to avoid submitting TextArea value on enter in IE. This is // another reason why widgets should inherit a common abstract // class instead of directly each other. + // This method is overridden only for IE and Firefox. } @Override diff --git a/uitest/src/com/vaadin/tests/components/ui/TextAreaEventPropagation.java b/uitest/src/com/vaadin/tests/components/ui/TextAreaEventPropagation.java new file mode 100644 index 0000000000..31eeac02da --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/TextAreaEventPropagation.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2014 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.ui; + +import com.vaadin.event.ShortcutAction.KeyCode; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.TextField; + +/** + * UI test for TextArea behavior when ENTER has been assigned as a keyboard + * shortcut. + * + * @author Vaadin Ltd + */ +public class TextAreaEventPropagation extends AbstractTestUIWithLog { + + protected static final String BUTTON_PRESSED = "Button Pressed"; + + protected static final String NO_BUTTON_PRESSED = "No Button Pressed"; + + private Label enterButtonPressed; + + private Label escapeButtonPressed; + + @Override + protected void setup(VaadinRequest request) { + + FormLayout form = new FormLayout(); + TextArea textArea = new TextArea("Text input"); + TextField textField = new TextField("Text field input"); + enterButtonPressed = new Label("Enter Label"); + enterButtonPressed.setCaption(NO_BUTTON_PRESSED); + escapeButtonPressed = new Label("Escape Label"); + escapeButtonPressed.setCaption(NO_BUTTON_PRESSED); + + Button enterButton = new Button("Enter"); + enterButton.setClickShortcut(KeyCode.ENTER); + enterButton.addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + + enterButtonPressed.setCaption(BUTTON_PRESSED); + } + }); + + Button escapeButton = new Button("Escape"); + escapeButton.setClickShortcut(KeyCode.ESCAPE); + escapeButton.addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + + escapeButtonPressed.setCaption(BUTTON_PRESSED); + } + }); + + form.addComponent(textArea); + form.addComponent(textField); + form.addComponent(enterButton); + form.addComponent(escapeButton); + form.addComponent(enterButtonPressed); + form.addComponent(escapeButtonPressed); + addComponent(form); + + } + + @Override + protected String getTestDescription() { + return "Currently if enter key is set as a shortcut for some component, it won't be possible for the user to enter newline in a textarea."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(12424); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/ui/TextAreaEventPropagationTest.java b/uitest/src/com/vaadin/tests/components/ui/TextAreaEventPropagationTest.java new file mode 100644 index 0000000000..11e0c52d27 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/ui/TextAreaEventPropagationTest.java @@ -0,0 +1,123 @@ +/* + * Copyright 2000-2014 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.ui; + +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 org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that the TextArea widget correctly stops ENTER events from propagating. + * + * @author Vaadin Ltd + */ +public class TextAreaEventPropagationTest extends MultiBrowserTest { + + @Test + public void testTextAreaEnterEventPropagation() throws InterruptedException { + openTestURL(); + WebElement textArea = vaadinElement("//TextArea[0]"); + Actions builder = new Actions(driver); + builder.click(textArea); + builder.sendKeys(textArea, "first line asdf"); + builder.sendKeys(Keys.ENTER); + builder.sendKeys(textArea, "second line jkl;"); + builder.perform(); + + WebElement enterLabel = driver.findElement(By.id("gwt-uid-8")); + String text = enterLabel.getText(); + assertEquals(TextAreaEventPropagation.NO_BUTTON_PRESSED, text); + + WebElement textField = vaadinElement("//TextField[0]"); + Actions builder2 = new Actions(driver); + builder2.click(textField); + + builder2.sendKeys("third line"); + builder2.sendKeys(Keys.ENTER); + + builder2.perform(); + + text = enterLabel.getText(); + + assertEquals(TextAreaEventPropagation.BUTTON_PRESSED, text); + + } + + @Test + public void testTextAreaEscapeEventPropagation() + throws InterruptedException { + openTestURL(); + WebElement textArea = vaadinElement("//TextArea[0]"); + Actions builder = new Actions(driver); + builder.click(textArea); + builder.sendKeys(textArea, "first line asdf"); + builder.sendKeys(Keys.ENTER); + builder.sendKeys(textArea, "second line jkl;"); + builder.sendKeys(Keys.ESCAPE); + builder.perform(); + + WebElement enterLabel = driver.findElement(By.id("gwt-uid-8")); + String text = enterLabel.getText(); + assertEquals(TextAreaEventPropagation.NO_BUTTON_PRESSED, text); + WebElement escapeLabel = driver.findElement(By.id("gwt-uid-10")); + text = escapeLabel.getText(); + assertEquals(TextAreaEventPropagation.BUTTON_PRESSED, text); + + } + + @Test + public void testTextFieldEscapeEventPropagation() + throws InterruptedException { + openTestURL(); + WebElement textArea = vaadinElement("//TextArea[0]"); + Actions builder = new Actions(driver); + builder.click(textArea); + builder.sendKeys(textArea, "first line asdf"); + builder.sendKeys(Keys.ENTER); + builder.sendKeys(textArea, "second line jkl;"); + builder.perform(); + + WebElement enterLabel = driver.findElement(By.id("gwt-uid-8")); + String text = enterLabel.getText(); + assertEquals(TextAreaEventPropagation.NO_BUTTON_PRESSED, text); + WebElement escapeLabel = driver.findElement(By.id("gwt-uid-10")); + + WebElement textField = vaadinElement("//TextField[0]"); + Actions builder2 = new Actions(driver); + builder2.click(textField); + + builder2.sendKeys("third line"); + builder2.sendKeys(Keys.ENTER); + builder2.sendKeys(Keys.ESCAPE); + + builder2.perform(); + + text = enterLabel.getText(); + assertEquals(TextAreaEventPropagation.BUTTON_PRESSED, text); + + text = escapeLabel.getText(); + + assertEquals(TextAreaEventPropagation.BUTTON_PRESSED, text); + + } + +} |