Fixed an issue where programmatically attaching and detaching a RichTextArea creates a JavaScript error because the RichTextArea uses a timeout to initialize its event system. When detach is called, RichTextArea attempts to unitialize the event system before it is completely setup.
Patch by: jlabanca
Review by: ecc (desk review)
Issue: 1897
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2536 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
index 8d568bc..5fcb331 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -33,6 +33,7 @@
@Override
public native void initElement() /*-{
var _this = this;
+ _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::initializing = true;
window.setTimeout(function() {
var elem = _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
var doc = elem.contentWindow.document;
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java
index 38fd83e..dca7920 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplMozilla.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -26,6 +26,7 @@
// fully loaded.
var _this = this;
var iframe = _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
+ _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::initializing = true;
iframe.onload = function() {
// Some Mozillae have the nasty habit of calling onload again when you set
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
index cde363f..0b688b6 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -33,6 +33,14 @@
*/
private Element beforeInitPlaceholder = DOM.createDiv();
+ /**
+ * Set to true when the {@link RichTextArea} is attached to the page and
+ * {@link #initElement()} is called. If the {@link RichTextArea} is detached
+ * before {@link #onElementInitialized()} is called, this will be set to
+ * false. See issue 1897 for details.
+ */
+ protected boolean initializing;
+
@Override
public native Element createElement() /*-{
return $doc.createElement('iframe');
@@ -66,6 +74,7 @@
// the iframe becomes attached to the DOM. Any non-zero timeout will do
// just fine.
var _this = this;
+ _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::initializing = true;
setTimeout(function() {
// Turn on design mode.
_this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.designMode = 'On';
@@ -224,6 +233,14 @@
@Override
public void uninitElement() {
+ // Issue 1897: initElement uses a timeout, so its possible to call this
+ // method after calling initElement, but before the event system is in
+ // place.
+ if (initializing) {
+ initializing = false;
+ return;
+ }
+
// Unhook all custom event handlers when the element is detached.
unhookEvents();
@@ -288,6 +305,13 @@
@Override
protected void onElementInitialized() {
+ // Issue 1897: This method is called after a timeout, during which time the
+ // element might by detached.
+ if (!initializing) {
+ return;
+ }
+ initializing = false;
+
super.onElementInitialized();
// When the iframe is ready, ensure cached content is set.
diff --git a/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java b/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
index 08dbb2f..9a55823 100644
--- a/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
+++ b/user/test/com/google/gwt/user/client/ui/RichTextAreaTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -23,6 +23,7 @@
*/
public class RichTextAreaTest extends GWTTestCase {
+ @Override
public String getModuleName() {
return "com.google.gwt.user.User";
}
@@ -41,6 +42,7 @@
// finish initializing (on some browsers).
this.delayTestFinish(1000);
new Timer() {
+ @Override
public void run() {
RootPanel.get().remove(area);
RootPanel.get().add(area);
@@ -54,6 +56,16 @@
}
/**
+ * Test that adding and removing an RTA before initialization completes
+ * doesn't throw an exception.
+ */
+ public void testAddRemoveBeforeInit() {
+ final RichTextArea richTextArea = new RichTextArea();
+ RootPanel.get().add(richTextArea);
+ RootPanel.get().remove(richTextArea);
+ }
+
+ /**
* Test that a delayed set of HTML is reflected. Some platforms have timing
* subtleties that need to be tested.
*/
@@ -61,6 +73,7 @@
final RichTextArea richTextArea = new RichTextArea();
RootPanel.get().add(richTextArea);
new Timer() {
+ @Override
public void run() {
richTextArea.setHTML("<b>foo</b>");
assertEquals("<b>foo</b>", richTextArea.getHTML().toLowerCase());
@@ -80,6 +93,7 @@
richTextArea.setHTML("<b>foo</b>");
assertEquals("<b>foo</b>", richTextArea.getHTML().toLowerCase());
new Timer() {
+ @Override
public void run() {
assertEquals("<b>foo</b>", richTextArea.getHTML().toLowerCase());
finishTest();
@@ -96,6 +110,7 @@
final RichTextArea richTextArea = new RichTextArea();
RootPanel.get().add(richTextArea);
new Timer() {
+ @Override
public void run() {
richTextArea.setText("foo");
assertEquals("foo", richTextArea.getText());
@@ -115,6 +130,7 @@
richTextArea.setText("foo");
assertEquals("foo", richTextArea.getText());
new Timer() {
+ @Override
public void run() {
assertEquals("foo", richTextArea.getText());
finishTest();