Easiest way to embed a Google map?

I’d like to find the easiest way to embed an API-based Google map. Ideally this should be nothing more than a div with an ID that I can resize via standard component methods, and the ability to execute JavaScript. executeJavaScript() seems to get me most of the way there, but it’s the div with an ID that is stumping me. Is there a simple way to create a component that is nothing more than a div?

Note that I know there are a variety of complicated ways to do this, ranging from writing multiple Vaadin classes to extending a GWT widget. But this doesn’t seem like it should be all that complicated, so I’m wondering if I’m missing it? I played around briefly with AbstractJavaScriptComponent and attempted to define its initialization JS in an executeJavaScript call, but the function wasn’t found even though it should have been defined correctly. AFAICT I need to define the JS in code since it references API keys configured within the Java/Scala side.

Thanks.

Hi,

Sounds like you are using Vaadin 6. Why don’y you use this addon
vaadin.com/directory#addon/googlemapwidget

I’m not, if I were then I’d use the addon.

In reading the docs more closely, it looks like what I want is to be able to use AbstractJavaScriptComponent, but to define my initialization function via addFunction. I’m doing something like this currently (Scala code):

class GoogleMap extends com.vaadin.ui.AbstractJavaScriptComponent {
addFunction(getClass.getName.replace(“.”, “_”), new JavaScriptFunction {
override def call(args:JSONArray) {
Page.current.p.getJavaScript.execute(“”“alert(“Ran!”)”“”)
}
})
}

but that complains about the initialization function not being found.

I need to access my Google API key, which is configured in Scala code from a configuration file. So that executeJavaScript call will eventually contain code to add a script element that refers to the API key. If I have to use JS, I guess I’d have to create some template/string substitution step as part of my build. Just seems like it’d be much cleaner if I could spit out my initialization function in code, plus that paves the way for using a Scala JavaScript DSL for enhanced type safety later.

I created today very simple example how to make custom google maps vaadin component.
Before you ask how to implement this in your code read this:
https://vaadin.com/book/vaadin7/-/page/gwt.javascript.html
and this:
http://demo.vaadin.com/book-examples-vaadin7/book#gwt.javascript.basic

gmap.js


var gmap = gmap || {};

gmap.GMap = function(element) {
	this.element = element;
	this.element.innerHTML = "<div id='map-canvas' style='height:100%; width:100%;'></div>";
	
	var me = this;

	$(function() {		
		window.initialize = function() {
			var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
			var mapOptions = {
				zoom : 4,
				center : myLatlng,
				mapTypeId : google.maps.MapTypeId.ROADMAP
			};

			var map = new google.maps.Map(
					document.getElementById('map-canvas'), mapOptions);
			
			var marker = new google.maps.Marker({
	            position: myLatlng,
	            map: map,
	            title: 'Hello World!'
	        });
			
		    // Getter and setter for the value property
		    me.getValue = function () {
		    	console.log('getValue ->', marker);
		    	return marker.getTitle();
		    };
		    me.setValue = function (value) {
		    	console.log('setValue ->', value);
		    	marker.setTitle(value);
		    	console.log('setted value ->', marker);
		    };
			
			google.maps.event.addListener(map, 'click', function() {
				me.click();
			});
		};

		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&'
				+ 'callback=initialize';
		document.body.appendChild(script);
	});
};

gmap-connector.js


window.com_example_components_gmap_GMap =
    function() {
        // Create the component
        var gMap = new gmap.GMap(this.getElement());
        
        // Handle changes from the server-side
        this.onStateChange = function() {
        	console.log('state change ->', this.getState().value);
        	gMap.setValue(this.getState().value);
        };
    
        // Pass user interaction to the server-side
        var connector = this;
        gMap.click = function() {
            connector.onClick(gMap.getValue());
        };
    };

GMap.java


@JavaScript({
		"http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js",
		"gmap.js", "gmap-connector.js" })
public class GMap extends AbstractJavaScriptComponent {
	
    public interface ValueChangeListener extends Serializable {
        void valueChange();
    }
    
    ArrayList<ValueChangeListener> listeners =
            new ArrayList<ValueChangeListener>();
    public void addListener(ValueChangeListener listener) {
        listeners.add(listener);
    }
    
    public void setValue(String value) {
        getState().setValue(value);
        markAsDirty();
    }
    
    public String getValue() {
        return getState().getValue();
    }
	
    @Override
    public GMapState getState() {
        return (GMapState) super.getState();
    }
    
    public GMap() {
        addFunction("onClick", new JavaScriptFunction() {
            @Override
            public void call(JSONArray arguments)
                    throws JSONException {
                getState().setValue(arguments.getString(0));
                for (ValueChangeListener listener: listeners)
                    listener.valueChange();
            }
        });
    }
}

GMapState.java


public class GMapState extends JavaScriptComponentState {
    private String value;
    
    public String getValue() {
        return value;
    }
    
    public void setValue(String value) {
        this.value = value;
    }
}

Has anyone successfully attempted the example above? I am trying to get it to work, but I keep running into a javascript exception.
[b]

Uncaught client side exception
JavaScriptException: (TypeError) : Object [object Object]
has no method ‘setValue’

[/b]
The only change i’ve made to the above code was to update the connector with the correct package path.

Any ideas or thoughts would be appreciated.

UPDATE: this error only seemed to pop up in debug mode. I’ve ignored it and moved on.

Note: in the gmap.js code above you may need to make the following change in order to see the map:


 this.element.innerHTML = "<div id='map-canvas' style='height:300px; width:300px;'></div>";
 

The main point is the size needs to be set some where. Maybe this is just a general Vaadin todo, but it stumped me for a bit.

I think Nolan is right to ask for an
easy
way to embed a Google map. In fact in modern web applications it’s such a common task that it should really be a no-brainer. Seems that a special widget (like the 6 add-on) is the right way to do this, but it’s such a valuable standard thing that it should be part of core Vaadin.

Those code examples Łukasz posted could be wrapped into an add-on of itself. The only difference to a normal add-on would be that this one wouldn’t require a widgetset compile as it is already javascript. It’s an easy grab for a popular add-on.

Łukasz thank you very much for your effort to develop and post this code!

With it I was able to port my javascript site to Vaadin easily and I’m sure this will help many others…

helllo, i’m new in vaadin too, and i tryed to compile this code and tomcat give me this:

HTTP Status 404 - /map/

type Status report

message /map/

description The requested resource is not available.

Can you pass me the project?

I need put a map in a personal project

Hi,
i write some code for GeoLocation for current position in Google maps using vaadin 7 components and java script. it’s showing correct output in Web-browser, but its not showing in Mobile browser. it’s any solution?