Adding a div element inside a panel?

陌路散爱 提交于 2019-12-23 03:51:45

问题


I'm working with GWT and I'm trying to add google-maps to my website. Since I want to use google-maps V3 I'm using JSNI. In order to display the map in my website I need to create a div element with id="map" and get it in the initialization function of the map. I did so, and it worked out fine but its location on the webpage is funny and I want it to be attached to a panel I'm creating in my code. So my question is how can I do it? Can I create a div somehow with GWT inside a panel ?

I've tried to do create a new HTMLPanel like this:

runsPanel.add(new HTMLPanel("<div id=\"map\"></div>"));

Where runsPanel is a the panel I want to to be attached to. Yet, it fails to retrive the div when I use the following initialization function:

private native JavaScriptObject initializeMap() /*-{

    var latLng = new $wnd.google.maps.LatLng(31.974, 34.813); //around Rishon-LeTsiyon
    var mapOptions = {
        zoom : 14,
        center : latLng,
        mapTypeId : $wnd.google.maps.MapTypeId.ROADMAP
    };
    var mapDiv = $doc.getElementById('map');
    if (mapDiv == null) {
        alert("MapDiv is null!");
    }
    var map = new $wnd.google.maps.Map(mapDiv, mapOptions);
    return map;

}-*/;

(It pops the alert - "MapDiv is null!")

Any ideas? Thanks


回答1:


You need to make sure initializeMap() is called on load, to verify the DOM element is accessible.

Try and refresh your approach and use another technique to create the maps panel:

  1. Extend Widget to define a custom widget that will be used for the Google Maps container:

    public class MapPanel extends Widget {
    
        private Element container;
    
        public MapPanel() {
    
            container = DOM.createDiv();
            container.setId("map");
    
            // this is required by the Widget API to define the underlying element
            setElement(container);
        }
    
        @Override
        protected void onLoad() {
            super.onLoad();
    
                initializeMap();
            }
        }
    }
    
  2. Invoke initialization:

    runsPanel.add(new MapPanel());
    

There are other issues, like the id attribute, hard-coded in the JSNI method and forcing duplication of code, and the proper location for initializeMap() and whether to create an overlay type for the JSNI layer, but that's outside the scope here.

References:

  • GWT post on Widget best practices
  • Google developers reference on Overlay types



回答2:


Your code works fine, if you make sure to attach runsPanel to the DOM before calling initializeMap().

You can test it with this simple EntryPoint:

@Override
public void onModuleLoad() {

  final Panel runsPanel = new ...Panel; /* Use the kind of panel you like */

  runsPanel.add(new HTMLPanel("<div id=\"map\"></div>"));

  RootLayoutPanel.get().add(runsPanel);

  initializeMap();
}

It's not enough to add the HTMLPanel to the runsPanel. If the runsPanel itself isn't attached to the DOM, then $doc.getElementById('map') cannot find anything.

Note: Make sure to set the height of the "map" div somehow, otherwise you won't see the map.




回答3:


You might want to simplify things by using UiBinder; see the Hello World example here: https://developers.google.com/web-toolkit/doc/latest/DevGuideUiBinder

UiBinder lets you write XML that defines the structure of the UI layout, similar to the way you can lay out a page using HTML. However the XML can construct widgets, such as buttons, etc. Further, you can attach a name to an XML element and refer to it in your Java code to bind event handlers to it, etc. It works great and it makes code very easy to read.

Further, however, in these situations, UiBinder can make the native HTML elements for you and nest them the way you want, rather than having to call methods to make widgets and put them inside other widgets. Further, however, the UiBinder documentation says that UiBinder can do a better job of using the browsers native way of representing things, supposedly resulting in more efficient code (from the above link):

Besides being a more natural and concise way to build your UI than doing it through code, UiBinder can also make your app more efficient. Browsers are better at building DOM structures by cramming big strings of HTML into innerHTML attributes than by a bunch of API calls. UiBinder naturally takes advantage of this, and the result is that the most pleasant way to build your app is also the best way to build it.

I think this feature might make it more likely for the browser to correctly register your widgets so they are found later by getElementById().

Your above code might look like this in UiBinder:

<g:HTMLPanel ui:field='my_HTMLPanel'>
  <div ui:field='map_div'>
    <!-- put some HTML here -->
  </div>
</g:HTMLPanel>


来源:https://stackoverflow.com/questions/10643041/adding-a-div-element-inside-a-panel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!