Search code examples
javascriptgwtdomjsni

Waiting for DOM to load in JSNI GWT


I'm currently having a problem where the javascript seems to be executing before the DOM is completely loaded. Why do i say this? Take the following code:

var $r = $wnd.Raphael("container", 640, 480);

// Creates pie chart at with center at 320, 200,
// radius 100 and data: [55, 20, 13, 32, 5, 1, 2]
$r.piechart(320, 240, 100, [ 55, 20, 13, 32, 5, 1, 2 ]);

returns a Javascript exception: 'f is null'. Which seems to indicate that the container name is not recognized.

If specify absolute coordinates the piechart is rendered fine. If i use the previous code in the Chrome console (after all is loaded) it effectively, loads the piechart into the container tag.

I've tried wrapping the block of code in a JQuery call:

$wnd.jQuery(function($) {
            // Creates canvas 640 × 480 at 10, 50
            var $r = $wnd.Raphael("container", 640, 480);
            // Creates pie chart at with center at 320, 200,
            // radius 100 and data: [55, 20, 13, 32, 5, 1, 2]
            $r.piechart(320, 240, 100, [ 55, 20, 13, 32, 5, 1, 2 ]);
    });

... And no dice.

Any ideias of what i could try?

EDIT:

Here's how/where i'm calling the JSNI method. The following is the relevant View code.

public class WidgetSamplerView extends AbstractPanelView implements
                WidgetSamplerPresenter.Display { 

private FlexTable mainPanel;

public WidgetSamplerView() {
        super();

            mainPanel = new FlexTable();

            HTML container = new HTML();
        container.getElement().setAttribute("style",
                "width:700px;height:700px");
        container.getElement().setId("container");

        mainPanel.setWidget(0, 1, container);

        MyRaphaelWrapper.pieChart(); // JSNI Call

        setWidget(mainPanel);
    }
}

Solution

  • You must make sure you call the JSNI method only when onLoad() is activated, to verify the widget has loaded.

    See another answer of mine on best practices for creating and initializing widgets, for a quick reference.

    The basic idea is to override onLoad() on the widget and call any loading functionality there:

    public class MainPanel extends FlexTable {
    
        private Element container;
    
        public MainPanel() {
    
            container = DOM.createDiv();
            container.setId("container");
    
            // this is required by the Widget API to define the underlying element
            setElement(container);
        }
    
        @Override
        protected void onLoad() {
            super.onLoad();
    
                MyRaphaelWrapper.pieChart(); // JSNI Call
            }
        }
    }