Author: [email protected]
Date: Mon Jun 29 10:34:10 2009
New Revision: 5637

Modified:
    trunk/user/src/com/google/gwt/user/client/ui/RichTextArea.java
     
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
     
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
    trunk/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java

Log:
Adds some assertions to RichTextArea to prevent users from using the  
formatters before the RichTextArea is initialized.

Patch by: jlabanca
Review by: jgw
Issue: 2749



Modified: trunk/user/src/com/google/gwt/user/client/ui/RichTextArea.java
==============================================================================
--- trunk/user/src/com/google/gwt/user/client/ui/RichTextArea.java       
(original)
+++ trunk/user/src/com/google/gwt/user/client/ui/RichTextArea.java      Mon Jun 
 
29 10:34:10 2009
@@ -43,10 +43,19 @@
      SourcesMouseEvents, HasAllMouseHandlers {

    /**
+   * <p>
     * This interface is used to access basic formatting options, when  
available.
     * If the implementation supports basic formatting, then
     * {...@link RichTextArea#getBasicFormatter()} will return an instance of  
this
     * class.
+   * </p>
+   * <p>
+   * The formatter will format the user selected text in the
+   * {...@link RichTextArea}.  As a result, it will only work reliably if the
+   * {...@link RichTextArea} is attached, visible to on the page, and has been
+   * focused at least once.  If you just want to initialize the content of
+   * the {...@link RichTextArea}, use {...@link RichTextArea#setHTML(String)}  
instead.
+   * </p>
     */
    public interface BasicFormatter {

@@ -166,10 +175,19 @@
    }

    /**
+   * <p>
     * This interface is used to access full formatting options, when  
available.
     * If the implementation supports full formatting, then
     * {...@link RichTextArea#getExtendedFormatter()} will return an instance  
of this
     * class.
+   * </p>
+   * <p>
+   * The formatter will format the user selected text in the
+   * {...@link RichTextArea}.  As a result, it will only work reliably if the
+   * {...@link RichTextArea} is attached, visible to on the page, and has been
+   * focused at least once.  If you just want to initialize the content of
+   * the {...@link RichTextArea}, use {...@link RichTextArea#setHTML(String)}  
instead.
+   * </p>
     */
    public interface ExtendedFormatter extends BasicFormatter {

@@ -363,7 +381,9 @@
    }

    /**
-   * Gets the basic rich text formatting interface.
+   * Gets the basic rich text formatting interface.  Note that formatting  
can
+   * only be done when the {...@link RichTextArea} is attached, visible on the
+   * page, and has been focused by the user.
     *
     * @return <code>null</code> if basic formatting is not supported
     */
@@ -375,7 +395,9 @@
    }

    /**
-   * Gets the full rich text formatting interface.
+   * Gets the full rich text formatting interface.  Note that formatting  
can
+   * only be done when the {...@link RichTextArea} is attached, visible on the
+   * page, and has been focused by the user.
     *
     * @return <code>null</code> if full formatting is not supported
     */

Modified:  
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
==============================================================================
---  
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java      
 
(original)
+++  
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java      
 
Mon Jun 29 10:34:10 2009
@@ -142,9 +142,4 @@
        elem.contentWindow.onblur = null;
      }
    }-*/;
-
-  @Override
-  boolean isRichEditingActive(Element elem) {
-    return true;
-  }
  }

Modified:  
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
==============================================================================
---  
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java 
 
(original)
+++  
trunk/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java 
 
Mon Jun 29 10:34:10 2009
@@ -15,6 +15,7 @@
   */
  package com.google.gwt.user.client.ui.impl;

+import com.google.gwt.core.client.JavaScriptException;
  import com.google.gwt.user.client.DOM;
  import com.google.gwt.user.client.Element;
  import com.google.gwt.user.client.ui.RichTextArea;
@@ -28,6 +29,13 @@
      RichTextArea.BasicFormatter, RichTextArea.ExtendedFormatter {

    /**
+   * The message displayed when the formatter is used before the  
RichTextArea
+   * is initialized.
+   */
+  private static final String INACTIVE_MESSAGE = "RichTextArea  
formatters " +
+      "cannot be used until the RichTextArea is attached and focused.";
+
+  /**
     * Holds a cached copy of any user setHTML/setText actions until the real
     * text area is fully initialized.  Becomes <code>null</code> after init.
     */
@@ -41,6 +49,11 @@
     */
    protected boolean initializing;

+  /**
+   * True when the element has been attached.
+   */
+  private boolean isReady;
+
    @Override
    public native Element createElement() /*-{
      return $doc.createElement('iframe');
@@ -247,6 +260,8 @@

    @Override
    public void uninitElement() {
+    isReady = false;
+
      // Issue 1897: initElement uses a timeout, so its possible to call this
      // method after calling initElement, but before the event system is in
      // place.
@@ -325,6 +340,7 @@
        return;
      }
      initializing = false;
+    isReady = true;

      super.onElementInitialized();

@@ -366,11 +382,17 @@
    }-*/;

    void execCommand(String cmd, String param) {
-    if (isRichEditingActive(elem)) {
+    assert isReady : INACTIVE_MESSAGE;
+    if (isReady) {
        // When executing a command, focus the iframe first, since some  
commands
        // don't take properly when it's not focused.
        setFocus(true);
-      execCommandAssumingFocus(cmd, param);
+      try {
+        execCommandAssumingFocus(cmd, param);
+      } catch (JavaScriptException e) {
+        // In mozilla, editing throws a JS exception if the iframe is
+        // *hidden, but attached*.
+      }
      }
    }

@@ -378,19 +400,18 @@
       
[email protected]::elem.contentWindow.document.execCommand(cmd,
  
false, param);
    }-*/;

-  native boolean isRichEditingActive(Element e) /*-{
-    return ((e.contentWindow.document.designMode).toUpperCase()) == 'ON';
-  }-*/;
-
    boolean queryCommandState(String cmd) {
-    if (isRichEditingActive(elem)) {
+    if (isReady) {
        // When executing a command, focus the iframe first, since some  
commands
        // don't take properly when it's not focused.
        setFocus(true);
-      return queryCommandStateAssumingFocus(cmd);
-    } else {
-      return false;
+      try {
+        return queryCommandStateAssumingFocus(cmd);
+      } catch (JavaScriptException e) {
+        return false;
+      }
      }
+    return false;
    }

    native boolean queryCommandStateAssumingFocus(String cmd) /*-{
@@ -398,10 +419,17 @@
    }-*/;

    String queryCommandValue(String cmd) {
-    // When executing a command, focus the iframe first, since some  
commands
-    // don't take properly when it's not focused.
-    setFocus(true);
-    return queryCommandValueAssumingFocus(cmd);
+    if (isReady) {
+      // When executing a command, focus the iframe first, since some  
commands
+      // don't take properly when it's not focused.
+      setFocus(true);
+      try {
+        return queryCommandValueAssumingFocus(cmd);
+      } catch (JavaScriptException e) {
+        return "";
+      }
+    }
+    return "";
    }

    native String queryCommandValueAssumingFocus(String cmd) /*-{

Modified:  
trunk/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
==============================================================================
--- trunk/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java  
(original)
+++ trunk/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java Mon  
Jun 29 10:34:10 2009
@@ -15,8 +15,10 @@
   */
  package com.google.gwt.user.client.ui;

+import com.google.gwt.core.client.GWT;
  import com.google.gwt.junit.client.GWTTestCase;
  import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.RichTextArea.BasicFormatter;

  /**
   * Tests the {...@link RichTextArea} widget.
@@ -63,6 +65,87 @@
      final RichTextArea richTextArea = new RichTextArea();
      RootPanel.get().add(richTextArea);
      RootPanel.get().remove(richTextArea);
+  }
+
+  public void testFormatAfterAttach() {
+    final RichTextArea area = new RichTextArea();
+    BasicFormatter formatter = area.getBasicFormatter();
+    RootPanel.get().add(area);
+    if (formatter != null) {
+      try {
+        formatter.toggleBold();
+        if (!GWT.isScript()) {
+          fail("Expected AssertionError");
+        }
+      } catch (AssertionError e) {
+        // Expected because the iframe is not initialized
+        return;
+      }
+      if (!GWT.isScript()) {
+        fail("Expected AssertionError");
+      }
+    }
+  }
+
+  public void testFormatAfterInitialize() {
+    final RichTextArea area = new RichTextArea();
+    RootPanel.get().add(area);
+
+    // This has to be done on a timer because the rta can take some time to
+    // finish initializing (on some browsers).
+    this.delayTestFinish(1000);
+    new Timer() {
+      @Override
+      public void run() {
+        BasicFormatter formatter = area.getBasicFormatter();
+        if (formatter != null) {
+          formatter.toggleBold();
+        }
+        RootPanel.get().remove(area);
+        finishTest();
+      }
+    }.schedule(500);
+  }
+
+  public void testFormatBeforeAttach() {
+    final RichTextArea area = new RichTextArea();
+    BasicFormatter formatter = area.getBasicFormatter();
+    if (formatter != null) {
+      try {
+        formatter.toggleBold();
+        if (!GWT.isScript()) {
+          fail("Expected AssertionError");
+        }
+      } catch (AssertionError e) {
+        // expected
+        return;
+      }
+      if (!GWT.isScript()) {
+        fail("Expected AssertionError");
+      }
+    }
+  }
+
+  public void testFormatWhenHidden() {
+    final RichTextArea area = new RichTextArea();
+    RootPanel.get().add(area);
+
+    // This has to be done on a timer because the rta can take some time to
+    // finish initializing (on some browsers).
+    this.delayTestFinish(1000);
+    new Timer() {
+      @Override
+      public void run() {
+        area.setVisible(false);
+        BasicFormatter formatter = area.getBasicFormatter();
+        if (formatter != null) {
+          // This won't work on some browsers, but it should return  
quietly.
+          formatter.toggleBold();
+        }
+        RootPanel.get().remove(area);
+        finishTest();
+      }
+    }.schedule(500);
    }

    /**

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to