diff options
author | Artur Signell <artur.signell@itmill.com> | 2012-08-08 14:56:05 +0000 |
---|---|---|
committer | Artur Signell <artur.signell@itmill.com> | 2012-08-08 14:56:05 +0000 |
commit | e03ac3fe1c5934cf24ed0aea58226baf43efb159 (patch) | |
tree | 0a0430d08e1567596521c39939224e95db4c9ef8 | |
parent | d5137280033543017834e4beb4c5b5f987120142 (diff) | |
download | vaadin-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
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&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> |