gavioto / clientsidegchart

Automatically exported from code.google.com/p/clientsidegchart
0 stars 2 forks source link

Charts broken under IE8 Standards Mode #12

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Display GChart demo page in IE8
2. Change document mode to IE8 Standards (Tools->Developer Tools(F12)->Document 
Mode in upper right menu)
3. (Alternatively - add <!doctype html> to GWT html page which switches to IE8 
standards too)

What is the expected output? What do you see instead?
I can see that some charts or their parts are not visible

What version of the product are you using? On what operating system?
2.7, windows 7 32-bit

Please provide any additional information below.
I would like to use Gchart within application which is written for IE8 
standards from scratch, thus I cannot force it to switch to IE quirks mode, 
where GChart works.
If you have any workaround to this problem it would be great!

Regards
Mike

Original issue reported on code.google.com by MikeDun...@centrum.cz on 15 Sep 2010 at 11:40

GoogleCodeExporter commented 9 years ago
I confirmed that this is a problem with the GWTCanvas library in 
gwt-incubator.jar (which the GChart live demo relies upon) by visiting that 
project's live demo, following your instructions, and verifying that the 
graphics blanks out in IE8 standards mode in their demo, too.

The simplest workaround is to force IE8 into IE7 Standards mode by placing the 
following line at the top of your page's <head> element:

<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
....other stuff in the head...
</head>

For more information about this workaround, follow the link at the top of this 
ajaxian post on the issue (which is where I got the above line from):

http://ajaxian.com/archives/the-vml-changes-in-ie-8

Other possible solutions:

o Use GChart's pure HTML rendering mode. You can do this for all your charts by 
simply commenting out the line that calls setCanvasFactory (which bolts 
GWTCanvas onto GChart). Or, you can do this on a per-curve basis by setting the 
fillSpacing of each curve to anything greater than 0. See the setCanvasFactory 
and setFillSpacing method's javadocs for more information. 

setCanvasFactory javadocs:

http://clientsidegchart.googlecode.com/svn/trunk/javadoc/com/googlecode/gchart/c
lient/GChart.html#setCanvasFactory%28com.googlecode.gchart.client.GChartCanvasFa
ctory%29

setFillSpacing javadocs:

http://clientsidegchart.googlecode.com/svn/trunk/javadoc/com/googlecode/gchart/c
lient/GChart.Symbol.html#setFillSpacing%28double%29

o Implement the GChartCanvasLite interface using a GWT graphics library that 
works in IE8 Standards mode. For example, I applied your instructions to the 
live demo for ITMill's gwt-graphics package, and it worked in IE8 Standards 
mode. So that avenue looks promising (I have not tried it yet, though). Here's 
the link to ITMill's gwt-graphics in case you want to try that route:

http://code.google.com/p/gwt-graphics/

GChartCanvasLite javadocs:

http://clientsidegchart.googlecode.com/svn/trunk/javadoc/com/googlecode/gchart/c
lient/GChartCanvasLite.html

Unless you really need IE8 Standards mode instead of IE7 standards mode (can't 
imagine why this should matter--IE7 standards mode is still standards mode as 
far as GWT is concerned) the meta tag fix I mentioned first is probably the way 
to go.

Thanks for reporting this problem. Please post back if you discover anything 
valuable to others as you workaround it.

Original comment by gchartco...@gmail.com on 18 Sep 2010 at 10:59

GoogleCodeExporter commented 9 years ago
Hello,

thank you for your suggestions.
I must use IE8 mode, because we develop application based on web standards that 
are supported only starting with IE8. Thus we support only IE8 and higher.

I read this great article about problems with IE8 & VML:
http://www.lrbabe.com/?p=104

Basically there are 2 problems (based on the article):
1) GWT Canvas registers bad VML namespace (IE8 changed this a bit)
2) GChart dynamically adds VML elements to element which is not yet attached to 
DOM. Such elements are not displayed at all! Article suggests to force IE 
display these elements by little trick: elem.outerHTML = elem.outerHTML and 
setting explicit width and height because it is lost somehow during dynamic 
injection...

I used the following code to overcome all issues:

...
GChartExample17 chart17 = new GChartExample17(); // creates chart with VML 
elements dynamically
RootPanel.get("rightBottomCell").add(chart17); // attaches chart into DOM
fix(chart17.getElement()); // add namespace and reattach elements
...

public static native void fix(Element el) /*-{
        var ua = navigator.userAgent.toLowerCase();
        if (ua.indexOf("msie") != -1 && $doc.documentMode && $doc.documentMode>=8) {
                if (!$doc.namespaces["v"]) {
                        $doc.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML");
                }
                var col = el.getElementsByTagName('shape');
                for(var i=0;i<col.length;i++) {
                        col[i].outerHTML = col[i].outerHTML;
                        col[i].style.width='10px';
                        col[i].style.height='10px';
                }
        }
}-*/;

This works like a charm.

To get rid of necessity of calling fix() method for each chart and each redraw, 
I tried to integrate it into GChart and gwt-canvas:

GChart.java:

@Override
protected void onAttach() {
  super.onAttach();
  fixVML(getElement());
}

private void realizePlotPanel() {
  ...
  fixVML(getElement());
}

private static native void fixVML(Element el) /*-{
  var ua = navigator.userAgent.toLowerCase();
  if (ua.indexOf("msie") != -1 && $doc.documentMode && $doc.documentMode>=8) {
    var col = el.getElementsByTagName('shape');
    for(var i=0;i<col.length;i++) {
      col[i].outerHTML = col[i].outerHTML;
      col[i].style.width='10px';
      col[i].style.height='10px';
    }
  }
}-*/;

GWTCanvasImplIE6.java
protected static native void init() /*-{
  if (!$doc.namespaces["v"]) {
    if($doc.documentMode &&$doc.documentMode>=8) {
      $doc.namespaces.add("v", "urn:schemas-microsoft-com:vml", "#default#VML");
    } else {
      $doc.namespaces.add("v", "urn:schemas-microsoft-com:vml");
      $doc.createStyleSheet().cssText = "v\\:*{behavior:url(#default#VML);}";
  }
}
}-*/;

(note that there is no IE8 version of this class and since the method which 
registeres VML namespace is static I cannot easily derive IE8 subclass which 
inherits from IE6 class and replace it via deferred binding)

I haven't noticed any performance issues by calling the fixVML() method which 
reattaches VML elements (called from realizePlotPanel()).

These steps are only for those who really need to support IE8 compatibility 
mode and want to have nice charts (vml looks better than pure html rendering 
mode). Others should use simpler workarounds as you suggested.

Regards
Mike

Original comment by MikeDun...@centrum.cz on 11 Oct 2010 at 7:17

GoogleCodeExporter commented 9 years ago
Just when you thought you escaped DLL hell, voila, VML hell.

Have not actually tried your code but seems like a winner based on my reading 
of it: a great post not just for GChart users but for anyone who uses GWTCanvas 
in IE8 standards mode.

I was not aware of the constraint that you must add the chart to the DOM before 
adding VML in IE8 standards. Good to know. My recollection is that in some 
browsers (FF?) doing it that way can make rendering a bit slower, but those 
browsers are much faster than IE anyway.

I got a very low opinion of the quality of VML based on the number of probably 
VML-based bugs in GWTCanvas that I had to work around to get GWTCanvas to work 
with GChart--and that was before this latest round of new IE8 VML bugs. 
Officially, VML support was dropped by Microsoft ages ago so I guess we should 
be grateful all that is needed is a few gratuitous assignments and such to make 
it work in IE8 standards.

Original comment by gchartco...@gmail.com on 16 Oct 2010 at 4:44