Tuesday, September 27, 2011

Support GWTCanvas in IE7 and 8

HTML5 is out for quite a long time now. The most popular thing is, I think, Canvas. It is being used for drawing, image editing, charting, games, intros and many more things.

I had created an image editor for a client who wanted me to make it work at internet explorer 7 and 8 also. As internet explorer doesn't support html5 so I had to use excanvas to make the application work in IE7 and 8. It was a tough job and I was annoyed by the client's insist on these version of internet explorer. I was like, who is going to use such old versions of a browser when we have a lots of choices plus chorme and FireFox are getting more and more popular. After I finished the application and made it work on all major browsers (including internet explorer 7 and 8) I got another project in which client wanted to make his GWTCanvas application run at IE7 and 8. I was again shocked why people are so serious about these old browsers.

In those days my computer had become very slow, I had tried many tricks but nothing worked. So I had to restore my operating system factory state. After I restored the initial installation (three years old) of windows vista I had internet explorer running on my computer. I was ready to upgrade it to internet explorer 9. But when I tried to do so I got to know that I had to install many service packs. I started downloading the service packs. There were lots of problems while trying to apply service packs and update the operating system. So I had IE7 on my computer for many days. Now I know why clients insist on supporting these old browsers.

Now lets talk about how we can make GWTCanvas run on the IE7 and 8. Because old browsers don't have Html5 support so GWT guys has not supported it their implementation also. If you try to simply add excanvas.js in your html file, it will not work. This is because that GWT canvas module has following lines in their .gwt.xml file.


Due to the above lines when you will try to run following line you will not get the canvas element in you application.

canvas = Canvas.createIfSupported();
 
GWT knows that the user is running the application in internet explorer 7/8 so the canvas support is not present. To overcome this problem you will have to override the "canvasElementSupport" property by adding following lines in your GWTExCanvas module



Notice that previously the value of canvasElementSupport was "no" and now it is "maybe". Including these lines will make the canvas available in internet explorer 7/8 too. But the canvas will still not get created. This is because the GWT's implementation of DOM doesn't have a way to create html element for Canvas. To add this support we will have to subclass the com.google.gwt.dom.client.DOMImplIE8 so that we can add the method createElement for html canvas element. We will have to put our class in same package as DOMImplIE8. Following is my implementation of this class.

package com.google.gwt.dom.client;

public class MyDOMImplIE8 extends DOMImplIE8 {

     @Override
    public Element createElement(Document doc, String tagName) {

        Element elem = super.createElement(doc, tagName);
        if (tagName.equalsIgnoreCase("canvas")) {
            elem = createExCanvas();
        }
        return elem;
    }

    private native Element createExCanvas()/*-{
        var el = $doc.createElement('canvas');
        el.setAttribute("width",300);
        el.setAttribute("height",150);
        el = G_vmlCanvasManager.initElement(el);
        return el;                                                        
    }-*/;


Here G_vmlCanvasManager.initElement is to initiate excanvas.

Also add following lines in your .gwt.xml file.


Now the last point is where do we add the excanvas.js. You can let the users of our GWTExCanvas module add excanvas.js in their html file or include it in your own java code. I preferred the second option. I created a JSNI method and pasted the excanvas file in this method. The method was called in a static block inside the above class.

 static {
         initExCanvas();
     }


    private native static void initExCanvas()/*-{
// CONTENTS OF EXCANVAS.JS HERE
}-*/;

Now my own GWTExCanvas module was ready. I just have to add it in my application and use the standard GWTCanvas code. If you have already developed your application and now you want to add IE7/8 support, this solution is ideal as all you have to do is to inherit this module. Make sure to inherit it after inheriting GWT in your .gwt.xml file.

Thanks for reading.

14 comments:

  1. thanks,
    very helpful!
    was brewing my own native functions when and how to create the canvas when stumbling upon your blog. Your way is now mine preferred to, works nicely!

    ReplyDelete
  2. Could you please explain exactly how you include source of excanvas.js in your GWT module? I've tried as you suggested without no result.
    Does it have any relation with wrapping it in script tags and attach to DOM?

    ReplyDelete
  3. You can simply add the .js file in your html or create a java class and paste all the code in your native function as I have described in the end of this post.

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete
  5. I put the excanvas.js before my gwt module script in main html file

    But seems that G_vmlCanvasManager is undefined

    Thanks in advance for any help

    com.google.gwt.core.client.JavaScriptException: (TypeError): 'G_vmlCanvasManager' is undefined
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:237)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:132)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.dom.client.MyDOMImplIE8.createExCanvas(MyDOMImplIE8.java)

    ReplyDelete
  6. Please make sure that you have entered correct path to include excanvas code. Try creating instance of G_vmlCanvasManager in firebug.

    ReplyDelete