Work around IE6's inability to set innerHTML on a tbody element

Microsoft Internet Explorer 6 and later won't permit JavaScript to
set the innerHTML property of a tbody element to arbitrary text,
yet every other major browser supports this just fine.

To support IE we need to build our HTML inside of a dummy table,
and then move the DOM node for the new tbody over to the old table.
This requires reaching into the guts of HTMLTable and changing its
private final bodyElem field, not something we really should be
doing, but it works "well enough" in GWT 1.5.3 that we can get
away with it.  For now.

The better fix is to completely rewrite our FancyFlexTable such
that it better supports bulk rendering modes and isn't so tied
to the stock HTMLTable GWT implementation.

Bug: GERRIT-62
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-02-24 19:28:45 -08:00
parent 210ec2f970
commit e518671778
4 changed files with 97 additions and 16 deletions

View File

@@ -1,14 +1,15 @@
<module>
<!-- openid.AllowFrameImpl -->
<replace-with class="com.google.gerrit.client.openid.AllowFrameImplSafari">
<when-type-is class="com.google.gerrit.client.openid.AllowFrameImpl" />
<any>
<when-property-is name="user.agent" value="safari"/>
</any>
</replace-with>
<replace-with class="com.google.gerrit.client.openid.AllowFrameImplSafari">
<when-type-is class="com.google.gerrit.client.openid.AllowFrameImpl" />
<any>
<when-property-is name="user.agent" value="safari"/>
</any>
</replace-with>
<replace-with class="com.google.gerrit.client.openid.AllowFrameImpl">
<when-type-is class="com.google.gerrit.client.openid.AllowFrameImpl"/>
</replace-with>
<!-- /openid.AllowFrameImpl -->
<replace-with class="com.google.gerrit.client.ui.FancyFlexTableImplIE6">
<when-type-is class="com.google.gerrit.client.ui.FancyFlexTableImpl" />
<any>
<when-property-is name="user.agent" value="ie6"/>
</any>
</replace-with>
</module>

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.client.ui;
import com.google.gerrit.client.Gerrit;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
@@ -38,6 +39,9 @@ import java.util.Map.Entry;
public abstract class FancyFlexTable<RowItem> extends Composite implements
HasFocus {
private static final FancyFlexTableImpl impl =
GWT.create(FancyFlexTableImpl.class);
protected static final String MY_STYLE = "gerrit-ChangeTable";
protected static final String S_ICON_HEADER = "IconHeader";
protected static final String S_DATA_HEADER = "DataHeader";
@@ -111,7 +115,7 @@ public abstract class FancyFlexTable<RowItem> extends Composite implements
i.next();
i.remove();
}
DOM.setInnerHTML(table.getBodyElement(), body);
impl.resetHtml(table, body);
}
protected boolean onKeyPress(final char keyCode, final int modifiers) {
@@ -276,10 +280,6 @@ public abstract class FancyFlexTable<RowItem> extends Composite implements
}
protected static class MyFlexTable extends FlexTable {
@Override
public Element getBodyElement() {
return super.getBodyElement();
}
}
private static final native <ItemType> void setRowItem(Element td, ItemType c)/*-{ td["__gerritRowItem"] = c; }-*/;

View File

@@ -0,0 +1,29 @@
// Copyright 2009 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 the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.client.ui;
import com.google.gerrit.client.ui.FancyFlexTable.MyFlexTable;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.HTMLTable;
public class FancyFlexTableImpl {
public void resetHtml(final MyFlexTable myTable, final String body) {
DOM.setInnerHTML(getBodyElement(myTable), body);
}
protected static native Element getBodyElement(HTMLTable myTable)
/*-{ return myTable.@com.google.gwt.user.client.ui.HTMLTable::bodyElem; }-*/;
}

View File

@@ -0,0 +1,51 @@
// Copyright 2009 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 the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.client.ui;
import com.google.gerrit.client.ui.FancyFlexTable.MyFlexTable;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.HTMLTable;
public class FancyFlexTableImplIE6 extends FancyFlexTableImpl {
@Override
public void resetHtml(final MyFlexTable myTable, final String bodyHtml) {
final Element oldBody = getBodyElement(myTable);
final Element newBody = parseBody(bodyHtml);
assert newBody != null;
final Element tableElem = DOM.getParent(oldBody);
DOM.removeChild(tableElem, oldBody);
setBodyElement(myTable, newBody);
DOM.appendChild(tableElem, newBody);
}
private static Element parseBody(final String body) {
final Element div = DOM.createDiv();
DOM.setInnerHTML(div, "<table>" + body + "</table>");
final Element newTable = DOM.getChild(div, 0);
for (Element e = DOM.getFirstChild(newTable); e != null; e =
DOM.getNextSibling(e)) {
if ("tbody".equals(e.getTagName().toLowerCase())) {
return e;
}
}
return null;
}
private static native void setBodyElement(HTMLTable myTable, Element newBody)
/*-{ myTable.@com.google.gwt.user.client.ui.HTMLTable::bodyElem = newBody; }-*/;
}