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
-~----------~----~----~----~------~----~------~--~---

Reply via email to