summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur.signell@itmill.com>2012-08-08 14:56:05 +0000
committerArtur Signell <artur.signell@itmill.com>2012-08-08 14:56:05 +0000
commite03ac3fe1c5934cf24ed0aea58226baf43efb159 (patch)
tree0a0430d08e1567596521c39939224e95db4c9ef8
parentd5137280033543017834e4beb4c5b5f987120142 (diff)
downloadvaadin-framework-e03ac3fe1c5934cf24ed0aea58226baf43efb159.tar.gz
vaadin-framework-e03ac3fe1c5934cf24ed0aea58226baf43efb159.zip
Fixed TextArea maxlength so it is always enforced (#9199)
Uses native maxlength attribute for browsers which support it. svn changeset:24123/svn branch:6.8
-rw-r--r--src/com/vaadin/terminal/gwt/client/BrowserInfo.java78
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextArea.java91
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextField.java32
-rwxr-xr-xtests/testbench/com/vaadin/tests/components/textarea/TextAreaMaxLength.html53
4 files changed, 210 insertions, 44 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
index 4b9f3eacab..6a94611a60 100644
--- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
+++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
@@ -128,7 +128,7 @@ public class BrowserInfo {
if (browserDetails.isFirefox()) {
browserIdentifier = BROWSER_FIREFOX;
majorVersionClass = browserIdentifier
- + browserDetails.getBrowserMajorVersion();
+ + getBrowserMajorVersion();
minorVersionClass = majorVersionClass
+ browserDetails.getBrowserMinorVersion();
browserEngineClass = ENGINE_GECKO;
@@ -140,21 +140,21 @@ public class BrowserInfo {
} else if (browserDetails.isSafari()) {
browserIdentifier = BROWSER_SAFARI;
majorVersionClass = browserIdentifier
- + browserDetails.getBrowserMajorVersion();
+ + getBrowserMajorVersion();
minorVersionClass = majorVersionClass
+ browserDetails.getBrowserMinorVersion();
browserEngineClass = ENGINE_WEBKIT;
} else if (browserDetails.isIE()) {
browserIdentifier = BROWSER_IE;
majorVersionClass = browserIdentifier
- + browserDetails.getBrowserMajorVersion();
+ + getBrowserMajorVersion();
minorVersionClass = majorVersionClass
+ browserDetails.getBrowserMinorVersion();
browserEngineClass = ENGINE_TRIDENT;
} else if (browserDetails.isOpera()) {
browserIdentifier = BROWSER_OPERA;
majorVersionClass = browserIdentifier
- + browserDetails.getBrowserMajorVersion();
+ + getBrowserMajorVersion();
minorVersionClass = majorVersionClass
+ browserDetails.getBrowserMinorVersion();
browserEngineClass = ENGINE_PRESTO;
@@ -211,23 +211,23 @@ public class BrowserInfo {
}
public boolean isSafari4() {
- return isSafari() && browserDetails.getBrowserMajorVersion() == 4;
+ return isSafari() && getBrowserMajorVersion() == 4;
}
public boolean isIE6() {
- return isIE() && browserDetails.getBrowserMajorVersion() == 6;
+ return isIE() && getBrowserMajorVersion() == 6;
}
public boolean isIE7() {
- return isIE() && browserDetails.getBrowserMajorVersion() == 7;
+ return isIE() && getBrowserMajorVersion() == 7;
}
public boolean isIE8() {
- return isIE() && browserDetails.getBrowserMajorVersion() == 8;
+ return isIE() && getBrowserMajorVersion() == 8;
}
public boolean isIE9() {
- return isIE() && browserDetails.getBrowserMajorVersion() == 9;
+ return isIE() && getBrowserMajorVersion() == 9;
}
public boolean isChrome() {
@@ -255,8 +255,7 @@ public class BrowserInfo {
}
public boolean isFF4() {
- return browserDetails.isFirefox()
- && browserDetails.getBrowserMajorVersion() == 4;
+ return browserDetails.isFirefox() && getBrowserMajorVersion() == 4;
}
/**
@@ -292,7 +291,7 @@ public class BrowserInfo {
return -1;
}
- return browserDetails.getBrowserMajorVersion();
+ return getBrowserMajorVersion();
}
public float getOperaVersion() {
@@ -300,7 +299,7 @@ public class BrowserInfo {
return -1;
}
- return browserDetails.getBrowserMajorVersion();
+ return getBrowserMajorVersion();
}
public boolean isOpera() {
@@ -308,13 +307,11 @@ public class BrowserInfo {
}
public boolean isOpera10() {
- return browserDetails.isOpera()
- && browserDetails.getBrowserMajorVersion() == 10;
+ return browserDetails.isOpera() && getBrowserMajorVersion() == 10;
}
public boolean isOpera11() {
- return browserDetails.isOpera()
- && browserDetails.getBrowserMajorVersion() == 11;
+ return browserDetails.isOpera() && getBrowserMajorVersion() == 11;
}
public native static String getBrowserString()
@@ -475,4 +472,51 @@ public class BrowserInfo {
private int getOperatingSystemMajorVersion() {
return browserDetails.getOperatingSystemMajorVersion();
}
+
+ /**
+ * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome
+ * 4, 8 for Internet Explorer 8.
+ * <p>
+ * Note that Internet Explorer 8 and newer will return the document mode so
+ * IE8 rendering as IE7 will return 7.
+ * </p>
+ *
+ * @return The major version of the browser.
+ */
+ public int getBrowserMajorVersion() {
+ return browserDetails.getBrowserMajorVersion();
+ }
+
+ /**
+ * Returns the browser minor version e.g., 5 for Firefox 3.5.
+ *
+ * @see #getBrowserMajorVersion()
+ *
+ * @return The minor version of the browser, or -1 if not known/parsed.
+ */
+ public int getBrowserMinorVersion() {
+ return browserDetails.getBrowserMinorVersion();
+ }
+
+ /**
+ * Checks if the browser version is newer or equal to the given major+minor
+ * version.
+ *
+ * @param majorVersion
+ * The major version to check for
+ * @param minorVersion
+ * The minor version to check for
+ * @return true if the browser version is newer or equal to the given
+ * version
+ */
+ public boolean isBrowserVersionNewerOrEqual(int majorVersion,
+ int minorVersion) {
+ if (getBrowserMajorVersion() == majorVersion) {
+ // Same major
+ return (getBrowserMinorVersion() >= minorVersion);
+ }
+
+ // Older or newer major
+ return (getBrowserMajorVersion() > majorVersion);
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
index 0ed5887442..4ab27646ed 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextArea.java
@@ -5,12 +5,17 @@
package com.vaadin.terminal.gwt.client.ui;
import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.UIDL;
/**
@@ -24,10 +29,17 @@ import com.vaadin.terminal.gwt.client.UIDL;
*/
public class VTextArea extends VTextField {
public static final String CLASSNAME = "v-textarea";
+ private MaxLengthHandler maxLengthHandler = new MaxLengthHandler();
+ private boolean browserSupportsMaxLengthAttribute = browserSupportsMaxLengthAttribute();
public VTextArea() {
super(DOM.createTextArea());
setStyleName(CLASSNAME);
+ if (!browserSupportsMaxLengthAttribute) {
+ addKeyUpHandler(maxLengthHandler);
+ addChangeHandler(maxLengthHandler);
+ sinkEvents(Event.ONPASTE);
+ }
}
@Override
@@ -39,8 +51,69 @@ public class VTextArea extends VTextField {
setRows(uidl.getIntAttribute("rows"));
}
- if (getMaxLength() >= 0) {
- sinkEvents(Event.ONKEYUP);
+ }
+
+ private class MaxLengthHandler implements KeyUpHandler, ChangeHandler {
+
+ public void onKeyUp(KeyUpEvent event) {
+ enforceMaxLength();
+ }
+
+ public void onPaste(Event event) {
+ enforceMaxLength();
+ }
+
+ private void enforceMaxLength() {
+ if (getMaxLength() >= 0) {
+ Scheduler.get().scheduleDeferred(new Command() {
+ public void execute() {
+ if (getText().length() > getMaxLength()) {
+ setText(getText().substring(0, getMaxLength()));
+ }
+ }
+ });
+ }
+ }
+
+ public void onChange(ChangeEvent event) {
+ // Opera does not support paste events so this enforces max length
+ // for Opera.
+ enforceMaxLength();
+ }
+
+ }
+
+ protected boolean browserSupportsMaxLengthAttribute() {
+ BrowserInfo info = BrowserInfo.get();
+ if (info.isFirefox() && info.isBrowserVersionNewerOrEqual(4, 0)) {
+ return true;
+ }
+ if (info.isSafari() && info.isBrowserVersionNewerOrEqual(5, 0)) {
+ return true;
+ }
+ if (info.isIE() && info.isBrowserVersionNewerOrEqual(10, 0)) {
+ return true;
+ }
+ if (info.isAndroid() && info.isBrowserVersionNewerOrEqual(2, 3)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void updateMaxLength(int maxLength) {
+ if (browserSupportsMaxLengthAttribute) {
+ super.updateMaxLength(maxLength);
+ } else {
+ // Handled automatically by MaxLengthHandler
+ }
+ }
+
+ @Override
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ if (event.getTypeInt() == Event.ONPASTE) {
+ maxLengthHandler.onPaste(event);
}
}
@@ -57,20 +130,6 @@ public class VTextArea extends VTextField {
}-*/;
@Override
- public void onBrowserEvent(Event event) {
- if (getMaxLength() >= 0 && event.getTypeInt() == Event.ONKEYUP) {
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- if (getText().length() > getMaxLength()) {
- setText(getText().substring(0, getMaxLength()));
- }
- }
- });
- }
- super.onBrowserEvent(event);
- }
-
- @Override
public int getCursorPos() {
// This is needed so that TextBoxImplIE6 is used to return the correct
// position for old Internet Explorer versions where it has to be
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
index b05b9ba830..b24e304b82 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
@@ -385,20 +385,30 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
}
private void setMaxLength(int newMaxLength) {
- if (newMaxLength >= 0) {
+ if (newMaxLength >= 0 && newMaxLength != maxLength) {
maxLength = newMaxLength;
- if (getElement().getTagName().toLowerCase().equals("textarea")) {
- // NOP no maxlength property for textarea
- } else {
- getElement().setPropertyInt("maxLength", maxLength);
- }
+ updateMaxLength(maxLength);
} else if (maxLength != -1) {
- if (getElement().getTagName().toLowerCase().equals("textarea")) {
- // NOP no maxlength property for textarea
- } else {
- getElement().removeAttribute("maxLength");
- }
maxLength = -1;
+ updateMaxLength(maxLength);
+ }
+
+ }
+
+ /**
+ * This method is reponsible for updating the DOM or otherwise ensuring that
+ * the given max length is enforced. Called when the max length for the
+ * field has changed.
+ *
+ * @param maxLength
+ * The new max length
+ */
+ protected void updateMaxLength(int maxLength) {
+ if (maxLength >= 0) {
+ getElement().setPropertyInt("maxLength", maxLength);
+ } else {
+ getElement().removeAttribute("maxLength");
+
}
}
diff --git a/tests/testbench/com/vaadin/tests/components/textarea/TextAreaMaxLength.html b/tests/testbench/com/vaadin/tests/components/textarea/TextAreaMaxLength.html
new file mode 100755
index 0000000000..5fe43b7b7a
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/textarea/TextAreaMaxLength.html
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://arturwin.office.itmill.com:9999/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.textarea.TextAreaTest?debug&amp;restartApplication</td>
+ <td></td>
+</tr>
+<!--max length 5-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaTextAreaTest::PID_Smenu#item0</td>
+ <td>20,9</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaTextAreaTest::Root/VOverlay[0]/VMenuBar[0]#item5</td>
+ <td>43,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaTextAreaTest::Root/VOverlay[1]/VMenuBar[0]#item2</td>
+ <td>70,13</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaTextAreaTest::Root/VOverlay[2]/VMenuBar[0]#item5</td>
+ <td>40,9</td>
+</tr>
+<tr>
+ <td>enterCharacter</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaTextAreaTest::PID_StestComponent</td>
+ <td>0123456789</td>
+</tr>
+<tr>
+ <td>assertValue</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaTextAreaTest::PID_StestComponent</td>
+ <td>01234</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>