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