I am trying to display a google map with a marker. I am using React.js. The map displays in the correct location, but the marker does not show and I get multiple 'object is not extensible' error in the browser console
The code looks like this
/** #jsx React.DOM */
var Map = React.createClass({
initialize: function() {
var lat = parseFloat(this.props.lat);
var lng = parseFloat(this.props.lon);
var myPosition = new google.maps.LatLng(lat,lng);
var mapOptions = {
center: myPosition,
zoom: 8
};
var map = new google.maps.Map(this.getDOMNode(), mapOptions);
var marker = new google.maps.Marker({position: myPosition, title: 'Hi', map: map});
},
componentDidMount: function(){
this.initialize();
},
render:function(){
return <div className="map"/>
}
});
detailed errors from console:
Uncaught TypeError: Can't add property k, object is not extensible VM3577:92
Uncaught TypeError: Can't add property onerror, object is not extensible main.js:3
Uncaught TypeError: Can't add property k, object is not extensible VM3577:92
Uncaught TypeError: Cannot read property 'style' of undefined VM3577:69
Uncaught TypeError: Can't add property onerror, object is not extensible
Craig Savolainen has a nice explanation on using Google Maps as a React Component here, the gist for the example is here. I acomplished the marker render with the following code:
var ExampleGoogleMap = React.createClass({
getDefaultProps: function () {
return {
initialZoom: 8,
mapCenterLat: 43.6425569,
mapCenterLng: -79.4073126,
};
},
componentDidMount: function (rootNode) {
var mapOptions = {
center: this.mapCenterLatLng(),
zoom: this.props.initialZoom
},
map = new google.maps.Map(document.getElementById('react-valuation-map'), mapOptions);
var marker = new google.maps.Marker({position: this.mapCenterLatLng(), title: 'Hi', map: map});
this.setState({map: map});
},
mapCenterLatLng: function () {
var props = this.props;
return new google.maps.LatLng(props.mapCenterLat, props.mapCenterLng);
},
render: function () {
return (
<div className='map-gic'></div>
);
}
});
Working jsFiddle
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
Improve this question
Each location should be at the center of the map when selected from a dropdown of locations. The following code is what I used to implement what I currently have.
For more context, this map was built in webflow ( a low code platform) and I get each location from a collection (cms) list I created. I've called collection: "location" and each location contains a latitude and longitude (that's how the markers are plotted on the map)
How do I center each selected location? What code do I add and where should I add it in my existing code?
<script>
var MAPS = {
zoom: 7,
map: '',
markers: {},
infoWindow: null,
init: function (defaultCoordinates = {}) {
MAPS.create(defaultCoordinates);
MAPS.plotMarkers()
},
create: function (defaultCoordinates = {}) {
var mapDom = document.getElementById('map');
if (!defaultCoordinates['lat']) {
defaultCoordinates.lat = 55.03222;
defaultCoordinates.lng = -2.62529;
}
MAPS.map = new google.maps.Map(mapDom, {
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: true,
mapTypeControl: true,
fullscreenControl: true,
scrollwheel: true,
zoom: MAPS.zoom,
center: defaultCoordinates,
plotMarkers: function () {
var locations = MAPS.locations();
gmarkers = {};
for (var i = 0; i < locations.length; i++) {
gmarkers[locations[i][0]] = MAPS.createMarkers(new google.maps.LatLng(locations[i][2], locations[i][3]), // passing lat and long
locations[i][1]); // passing Info-window information
}
MAPS.markers = gmarkers;
},
initAutoComplete: function () {
var input = document.getElementById('search')
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.addListener('place_changed', () => {
const place = autocomplete.getPlace();
if (place.geometry) {
var lat = place.geometry.location.lat();
var lng = place.geometry.location.lng();
MAPS.init({
lat: lat,
lng: lng
});
var marker = new google.maps.Marker({
position: place.geometry.location,
map: MAPS.map,
});
}
});
},
openMarkerOnClick: function () {
var viewInMap = document.querySelectorAll('[data-marker-open]').addEventListener('click', function () {
console.log('clicked');
})
},
createMarkers: function (latlng, html) {
var marker = new google.maps.Marker({
position: latlng,
map: MAPS.map,
icon: 'https://uploads-ssl.webflow.com/63c7cbc99a05611a1bd1ae5a/63ce964d18ff37a39c305bcd_image%2011.png'
});
// Define info window for each marker
google.maps.event.addListener(marker, 'click', function () {
if (MAPS.infoWindow) {
MAPS.infoWindow.close();
}
console.log(MAPS.infoWindow)
MAPS.infoWindow = new google.maps.InfoWindow();
MAPS.infoWindow.setContent(html);
MAPS.infoWindow.open(MAPS.map, marker);
});
return marker;
},
locations: function () {
// Create a locations array
var locations = []
// Add .location-wrapper class to the location Collection Item
var dynPlaces = document.querySelectorAll('.w-dyn-item.location-item');
// Define variables for the map info window
dynPlaces.forEach(function (elem) {
// Create places array
var place = [];
// Define variables for each place
var dataTitle = elem.querySelector('.data---slug').innerText; // Define slug for targeting the information window
var dataLat = Number(elem.querySelector('.data---latitude').innerText); // Define latitude point for pin
var dataLong = Number(elem.querySelector('.data---longitude').innerText); // Define longitude point for pin
var infoWindowContent = elem.querySelector('.data---info-window').innerHTML; // Define content wrapper for the information window
place.push(dataTitle, infoWindowContent, dataLat, dataLong); // Add variables to each place
locations.push(place); // Add each place to the locations array
});
return locations;
},
build: function (defaultCoordinates = {}) {
MAPS.init(defaultCoordinates);
// MAPS.openMarkerOnClick();
}
}
function initMap() {
MAPS.build();
}
window.onload = (event) => {
MAPS.build();
MAPS.initAutoComplete();
};
</script>
I have a google.maps.Data layer with a polygon feature:
state = new google.maps.Data();
state.loadGeoJson('static/geojson/ga_state.geojson', {
idPropertyName: 'name'
});
state.setStyle({
clickable: false,
visible: false,
});
state.setMap(map);
Within this feature collection is a polygon representing the state of Georgia:
ga = state.getFeatureById('Georgia')
I can get the geometry of this feature:
gaGeom = ga.getGeometry()
But when I pass either of these objects and also the raw array to google.maps.geometry.polygon.containsFeature(), I get an error that the object does not contain the get() fuction:
google.maps.geometry.poly.containsLocation(p.getPosition(), ga)
Uncaught TypeError: b.get is not a function(…)
google.maps.geometry.poly.containsLocation(p.getPosition(), gaGeom)
Uncaught TypeError: b.get is not a function(…)
google.maps.geometry.poly.containsLocation(p.getPosition(), gaGeom.getArray())
Uncaught TypeError: b.get is not a function(…)
How can I get a google.maps.Data.Polygon to either convert to a google.maps.Polygon or to work with this function?
EDIT:
I have found a way to construct a google.maps.Polygon from a google.maps.Data.Polygon as:
//gaGeom is the feature.geometry from the data layer
poly = new google.maps.Polygon({paths:gaGeom.getAt(0).getArray()})
But surely there has to be a cleaner way to construct the google.maps.Polygon?
The google.maps.geometry.poly.containsLocation method takes a point (a google.maps.LatLng) and a polygon (a google.maps.Polygon).
containsLocation(point:LatLng, polygon:Polygon)
Return Value: boolean
Computes whether the given point lies inside the specified polygon.
ga = state.getFeatureById('Georgia') returns a "feature"
gaGeom = ga.getGeometry() returns a "Geometry"
gaGeom.getArray() returns an "Array" of LinearRings
None of which is a google.maps.Polygon. You can make a google.maps.Polygon from the Array (as I see you have discovered while I wrote this).
proof of concept
code:
function initialize() {
var map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var state = new google.maps.Data();
var poly;
state.addListener('addfeature', function(evt) {
if (evt.feature.getId() == "Georgia") {
var ga = state.getFeatureById('Georgia');
var gaGeom = ga.getGeometry();
//gaGeom is the feature.geometry from the data layer
poly = new google.maps.Polygon({
paths: gaGeom.getAt(0).getArray(),
map: map,
clickable: false
});
}
});
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(map, 'click', function(evt) {
infoWindow.setPosition(evt.latLng);
if (google.maps.geometry.poly.containsLocation(evt.latLng, poly)) {
infoWindow.setContent("INSIDE POLY<br>" + evt.latLng.toUrlValue(6));
} else {
infoWindow.setContent("OUTSIDE POLY<br>" + evt.latLng.toUrlValue(6));
}
infoWindow.open(map);
});
state.loadGeoJson("http://www.geocodezip.com/GeoJSON/gz_2010_us_040_00_500k.json.txt", {
idPropertyName: 'NAME'
});
state.setStyle({
clickable: false,
visible: false,
});
state.setMap(map);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': "State of Georgia"
}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
map.fitBounds(results[0].geometry.viewport);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
google.maps.event.addDomListener(window, "load", initialize);
In the Google Maps API v3 they have stated that we need to do this to open the infowindow when the marker gets clicked:
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
Now I am trying to duplicate this in dart using the js library. So far I have something like this:
final google_maps = context['google']['maps'];
var myLatlng = [43.5, -6.5];
var center = new JsObject(google_maps['LatLng'], myLatlng);
var mapTypeId = google_maps['MapTypeId']['ROADMAP'];
var mapOptions = new JsObject.jsify({
"center": center,
"zoom": 8,
"mapTypeId": mapTypeId
});
var map = new JsObject(google_maps['Map'], [querySelector('#map-canvas'), mapOptions]);
var marker = new JsObject(google_maps['Marker'], [new JsObject.jsify({
'position': center,
'map': map,
'title': 'Hello World!'
})]);
var tooltip = '<div id="content">Info window coontent</div>';
var infowindow = new JsObject(google_maps['InfoWindow'], [new JsObject.jsify({
"content": tooltip
})]);
google_maps['event'].callMethod('addListener', [marker, 'click', () {
infowindow.callMethod('open',[map,marker]);
}]);
The issue is that I set the 'addListener' method through google_maps['event'], but when I click the marker, I get a NoSuchMethodError:
Closure call with mismatched arguments: function 'call'
NoSuchMethodError: incorrect number of arguments passed to method named 'call'
Receiver: Closure: () => dynamic
Tried calling: call(Instance of 'JsObject')
Found: call()
I am aware that there is a google_maps dart package, but I want the interact with the javascript api using dart's js library.
Thanks in advance.
Your closure has zero arguments.
() {
infowindow.callMethod('open',[map,marker]);
}
You just have to give it an argument as stated in the error message:
(event) {
infowindow.callMethod('open',[map,marker]);
}
Thanks in advance for any help you can provide! I'm trying to create markers in my Google Map using JSON data. The good news is that I've got the data in the format I need it. The bad news is that I'm new to JSON, and I can't seem to get the markers to show up on the map. From the console's response, the issue seems to be the mapInit line at the bottom of the code below.
I have tried resolving this problem by reviewing solutions at different markers on google maps v3, Using JSON markers in Google Maps API with Javascript, and Google Maps API v3: Adding markers from an array doesn't work, among others. I've also tried duplicating the examples at http://weareallrobots.com/demos/map.html and other sites, but I'm still having trouble.
My code:
<script>
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var rendererOptions = {
draggable: true,
panel:document.getElementById('directions_panel')
};
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var mapOptions = {
zoom: 6,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsDisplay.setMap(map);
// HERE'S WHERE PROBLEMS START
$.getJSON("mapall.js", {}, function(data){
$.each(data.masterlocation, function(i, item){
$("#markers").append('<li>' + item.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(item.latitude, item.longitude),
map: map_canvas,
title: item.nickname
});
arrMarkers[i] = marker;
var infowindow = new google.maps.InfoWindow({
content: "<h3>"+ item.nickname +"</h3>"
});
arrInfoWindows[i] = infowindow;
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
});
});
}
function calcRoute() {
UNRELATED ROUTING CODE HERE
}
// HERE'S WHERE MORE PROBLEMS START
$(function(){
// initialize map (create markers, infowindows and list)
mapInit();
// "live" bind click event
$("#markers a").live("click", function(){
var i = $(this).attr("rel");
// this next line closes all open infowindows before opening the selected one
//for(x=0; x < arrInfoWindows.length; x++){ arrInfoWindows[x].close(); }
arrInfoWindows[i].open(map, arrMarkers[i]);
});
});
</script>
My JSON Data
[{"masterlocation":{"latitude":"33.5","nickname":"First","longitude":"-86.8"}},{"masterlocation":{"latitude":"34.7","nickname":"Second","longitude":"-86.6"}},
UPDATE 1
As per comments from geocodezip and Adam, I've updated my code to the below. I added the + symbol before latitude and longitude, and I replaced mapInit with initialize. However, I'm still not getting any markers to show up. Firebug is telling me that I have errors in my jQuery file, but I'm not sure if these are related. Thanks for sticking with me!
Code:
// HERE'S WHERE PROBLEMS START
$.getJSON("mapall.js", {}, function(data){
$.each(data.masterlocation, function(i, item){
$("#markers").append('<li>' + item.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(+item.latitude, +item.longitude),
map: map_canvas,
title: item.nickname
});
arrMarkers[i] = marker;
var infowindow = new google.maps.InfoWindow({
content: "<h3>"+ item.nickname +"</h3>"
});
arrInfoWindows[i] = infowindow;
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
});
});
}
function calcRoute() {
UNRELATED ROUTING CODE HERE
}
// HERE'S WHERE MORE PROBLEMS START
$(function(){
// initialize map (create markers, infowindows and list)
initialize();
// "live" bind click event
$("#markers a").live("click", function(){
var i = $(this).attr("rel");
// this next line closes all open infowindows before opening the selected one
//for(x=0; x < arrInfoWindows.length; x++){ arrInfoWindows[x].close(); }
arrInfoWindows[i].open(map, arrMarkers[i]);
});
});
JQuery errors
TypeError: a is undefined
[Break On This Error]
...rn a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){...
jquery.js (line 29)
TypeError: a is undefined
[Break On This Error]
...rn a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){...
UPDATE 2
My current code is below, as well as the error codes I am getting in the console. New errors appeared when I reloaded the page, and they refer to the line in my javascript where function initialize first occurs. Maybe this is the problem?
Also, is it possible that the problem is in the JSON? Each JSON entry is preceded by the name of the MYSQL table, "Masterlocation" (see above.) In other JSON examples I've seen, the term that comes after the "." in "$.each(data.masterlocation)" only occurs once.
My Javascript:
<script>
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var rendererOptions = {
draggable: true,
panel:document.getElementById('directions_panel')
};
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var mapOptions = {
zoom: 6,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsDisplay.setMap(map);
$.getJSON("mapall.js", {}, function(data){
console.log(data);
$.each(data.masterlocation, function(i, item){
console.log(item);
$("#markers").append('<li>' + item.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(+item.latitude, +item.longitude),
map: map,
title: item.nickname
});
arrMarkers[i] = marker;
var infowindow = new google.maps.InfoWindow({
content: "<h3>"+ item.nickname +"</h3>"
});
arrInfoWindows[i] = infowindow;
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
});
});
}
function calcRoute() {
ROUTING CODE
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: optimize,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var route = response.routes[0];
var summaryPanel = document.getElementById("directions_panel");
}
$(function(){
// initialize map (create markers, infowindows and list)
initialize();
// "live" bind click event
$("#markers a").live("click", function(){
var i = $(this).attr("rel");
// this next line closes all open infowindows before opening the selected one
//for(x=0; x < arrInfoWindows.length; x++){ arrInfoWindows[x].close(); }
arrInfoWindows[i].open(map, arrMarkers[i]);
});
});
</script>
Javascript Errors from Console: these only occurred after I reloaded the page.
Uncaught TypeError: Cannot read property 'length' of undefined jquery.js:29
c.extend.each jquery.js:29
(anonymous function) mapall:87
b jquery.js:121
w.onreadystatechange jquery.js:127
Uncaught TypeError: Cannot read property 'length' of undefined jquery.js:29
c.extend.each jquery.js:29
(anonymous function) mapall:87
b jquery.js:121
w.onreadystatechange jquery.js:127
In addition to any other errors, the way you're accessing the JSON data doesn't match the format of that data.
Your code to access the JSON data is:
$.getJSON( "mapall.js", {}, function( data ) {
$.each( data.masterlocation, function( i, item ) {
... use item.nickname, item.latitude, and item.longitude here
});
});
Now there's nothing wrong with that code, if the JSON data looked like this:
{
"masterlocation": [
{
"nickname": "First",
"latitude": 33.5,
"longitude": -86.8
},
{
"nickname": "Second",
"latitude": 34.7,
"longitude": -86.6
}
]
}
This JSON data is an object with a single property named masterlocation. That property is an array of objects, each one containing nickname, a string, and latitude and longitude, two numbers.
That's a pretty sensible way to lay out the JSON data. I would do it just about the same myself. (The only things I can think of changing would be the naming conventions: I'd probably use a name like locations instead of masterlocation because I like to see plural names for arrays, and I like shorter names for commonly-used properties, e.g. name, lat, and lng. But that's purely a matter of style—the structure I'd use is identical aside for names.)
Unfortunately, your actual JSON data looks like this:
[
{
"masterlocation": {
"latitude": "33.5",
"nickname": "First",
"longitude": "-86.8"
}
},
{
"masterlocation": {
"latitude": "34.7",
"nickname": "Second",
"longitude": "-86.6"
}
}
]
This is an array of two elements. Each element is an object with one property named masterlocation. Each masterlocation object contains the nickname, latitude, and longitude properties. And the latitude and longitude are strings instead of numbers like they should be.
It would be easy enough to change your code to work with this structure:
$.getJSON( "mapall.js", {}, function( data ) {
$.each( data, function( i, item ) {
var loc = item.masterlocation;
... use loc.nickname, +loc.latitude, and +loc.longitude here
});
});
But if you have the option of changing the format of your JSON format, I'd do that instead. You had the right idea in your JavaScript code, just change the JSON output to match.
Make sure the latitude and longitude are actually numbers in JS, not strings.
To do a type convert, just put a + in front of the string
position: new google.maps.LatLng(+item.latitude, +item.longitude)
For some reason, google's API was not built smart enough to handle passing in strings containing numbers....go figure.
EDIT
Ditto to the comment on your post as well - you are calling a function mapInit() but you should be calling the function initialize() from the looks of it.
EDIT2
This line:
map: map_canvas,
should be
map: map,
I'm developing an application with VB.NET and Google Maps v3 and trying create a map with these properties:
<script type="text/javascript">
$(document).ready(function (){
var sPath ="images/AppIcons/Vehicles/icon05.png,";
var markers= new google.maps.Marker({
position : new google.maps.LatLng(4.759915, -74.04083),
map : map,
icon : new google.maps.MarkerImage(+ sPath + null, null, null, new google.maps.Size(32, 32)),
animation: google.maps.Animation.DROP,
title : "buena"
});
var myLatlng = new google.maps.LatLng(0, 0);
var mapOptions={zoom: 3,center: new google.maps.LatLng(4.590798,-74.084244),mapTypeId: google.maps.MapTypeId.ROADMAP };
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var marker = setMarkers(map);
var infowindow = new google.maps.InfoWindow({Content : '<b>FM3200 - FM3200</b><div><font size=1> </font></div><div><u>20/01/2013 04:30:56 p.m. - Voltaje Externo - (Norte)</u></div>Ubicacion Invalida In1:0 In2:0 In3:0 Batext:4.45V Vel:0 Odom:0 Ibutton:0 Oficina Principal Risk, Kmh: 0'});
if (markers !='') {
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
/*if (marker.getAnimation() != null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}*/
});
}
});
function setMarkers(map,markers) {
var marker =markers;
if (marker !='') {
return marker;
}
}</script>
When I run this code, this error message appears:
Uncaught TypeError: Cannot read property '__e3_' of undefined main.js:18
How can I solve this error?
Move the creation of map to the top of the function.
Currently you use map as map-option for markers, where it's expected to be a google.maps.Map-instance(but it's undefined, because the map isn't created yet)