Author: [email protected]
Date: Tue Jun 23 13:30:29 2009
New Revision: 5615
Modified:
trunk/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
trunk/user/src/com/google/gwt/user/client/ui/impl/TextBoxImplIE6.java
trunk/user/test/com/google/gwt/user/client/ui/TextAreaTest.java
Log:
Fixes a bunch of IE bugs in TextArea related to weird handling of newline
characters.
Patch by: jlabanca
Review by: jgw
Issue: 427
Modified: trunk/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
==============================================================================
--- trunk/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
(original)
+++ trunk/user/src/com/google/gwt/user/client/ui/TextBoxBase.java Tue Jun
23 13:30:29 2009
@@ -294,6 +294,15 @@
impl.setSelectionRange(getElement(), pos, length);
}
+ /**
+ * Sets this object's text. Note that some browsers will manipulate the
text
+ * before adding it to the widget. For example, most browsers will
strip all
+ * <code>\r</code> from the text, except IE which will add a
<code>\r</code>
+ * before each <code>\n</code>. Use {...@link #getText()} to get the text
+ * directly from the widget.
+ *
+ * @param text the object's new text
+ */
public void setText(String text) {
DOM.setElementProperty(getElement(), "value", text != null ?
text : "");
}
Modified:
trunk/user/src/com/google/gwt/user/client/ui/impl/TextBoxImplIE6.java
==============================================================================
--- trunk/user/src/com/google/gwt/user/client/ui/impl/TextBoxImplIE6.java
(original)
+++ trunk/user/src/com/google/gwt/user/client/ui/impl/TextBoxImplIE6.java
Tue Jun 23 13:30:29 2009
@@ -42,31 +42,75 @@
var tr = elem.document.selection.createRange();
if (tr.parentElement() !== elem)
return 0;
- return tr.text.length;
+ var trLength = tr.text.length;
+
+ // Subtract characters from the end to account for trimmed newlines.
+ var offset = 0;
+ var tr2 = tr.duplicate();
+ tr2.moveEnd('character', -1);
+ var tr2Length = tr2.text.length;
+ while (tr2Length == trLength && tr2.parentElement() == elem &&
tr.compareEndPoints('StartToEnd', tr2) <= 0) {
+ offset += 2;
+ tr2.moveEnd('character', -1);
+ tr2Length = tr2.text.length;
+ }
+ return trLength + offset;
}
catch (e) {
return 0;
}
}-*/;
+ /**
+ * The text reported in the text range does not include newline
characters at
+ * the end of the selection. So, we need to create 2 ranges and subtract
a
+ * character from one until the lengths are different. At that point, we
know
+ * exactly how many \r\n were truncated from the selection.
+ */
@Override
public native int getTextAreaCursorPos(Element elem) /*-{
try {
var tr = elem.document.selection.createRange();
+ if (tr.parentElement() !== elem)
+ return -1;
var tr2 = tr.duplicate();
tr2.moveToElementText(elem);
- tr.setEndPoint('EndToStart', tr2);
- return tr.text.length;
+ tr2.setEndPoint('EndToStart', tr);
+ var tr2Length = tr2.text.length;
+
+ // Subtract characters from the end to account for trimmed newlines.
+ var offset = 0;
+ var tr3 = tr2.duplicate();
+ tr3.moveEnd('character', -1);
+ var tr3Length = tr3.text.length;
+ while (tr3Length == tr2Length && tr3.parentElement() == elem) {
+ offset += 2;
+ tr3.moveEnd('character', -1);
+ tr3Length = tr3.text.length;
+ }
+ return tr2Length + offset;
}
catch (e) {
return 0;
}
}-*/;
+ /**
+ * Moving the start 1 character will move across a \r\n, but \r\n counts
as
+ * two characters, so we need to offset the position accordingly.
+ */
@Override
public native void setSelectionRange(Element elem, int pos, int length)
/*-{
try {
var tr = elem.createTextRange();
+ var newlinesWithin = elem.value.substr(pos,
length).match(/(\r\n)/gi);
+ if (newlinesWithin != null) {
+ length -= newlinesWithin.length;
+ }
+ var newlinesBefore = elem.value.substring(0, pos).match(/(\r\n)/gi);
+ if (newlinesBefore != null) {
+ pos -= newlinesBefore.length;
+ }
tr.collapse(true);
tr.moveStart('character', pos);
tr.moveEnd('character', length);
Modified: trunk/user/test/com/google/gwt/user/client/ui/TextAreaTest.java
==============================================================================
--- trunk/user/test/com/google/gwt/user/client/ui/TextAreaTest.java
(original)
+++ trunk/user/test/com/google/gwt/user/client/ui/TextAreaTest.java Tue Jun
23 13:30:29 2009
@@ -21,9 +21,50 @@
*/
public class TextAreaTest extends TextBoxBaseTestBase {
+ /**
+ * Most browsers strip \r from newlines, but IE adds them in. IE's
TextRange
+ * also truncates the \r\n from the end of the selected range. This test
is
+ * designed to work on all browsers and verifies that the newlines are
+ * accounted for in all browsers.
+ */
+ public void testNewline() {
+ testNewline("Hello World\r\n\r\n\r\n\r\n\r\n", 15, 6, 15);
+ testNewline("Hello\r\n\r\n\r\n\r\nWorld, My name is John.", 7, 3, 15);
+ testNewline("\r\n\r\n\r\n\r\n\r\nHello World", 4, 4, 13);
+ testNewline("\r\n\r\n\r\n\r\n\r\n", 2, 2, 4);
+ }
+
@Override
protected TextBoxBase createTextBoxBase() {
return new TextArea();
}
+ /**
+ * Test the handling of newline characters.
+ *
+ * @param text the text to test
+ * @param cursorPos the cursor position within the newlines
+ * @param startRange the start of a range that includes newlines
+ * @param endRange the end of a range that includes newlines
+ */
+ private void testNewline(String text, int cursorPos, int startRange,
+ int endRange) {
+ TextBoxBase box = createTextBoxBase();
+ box.setText(text);
+ RootPanel.get().add(box);
+
+ // Browsers will manipulate the text when attached to the DOM, so we
need
+ // to get the new value.
+ text = box.getText();
+
+ // Position the cursor in the newlines
+ box.setCursorPos(cursorPos);
+ assertEquals(cursorPos, box.getCursorPos());
+
+ // Select newlines
+ box.setSelectionRange(startRange, endRange - startRange);
+ assertEquals(text.substring(startRange, endRange),
box.getSelectedText());
+
+ RootPanel.get().remove(box);
+ }
}
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---