Google Maps API会在表单中添加标记,但只有在第二次单击后才会添加getElementById

时间:2016-05-29 15:51:28

标签: javascript google-maps google-maps-api-3

我尝试在InfoWindow中插入带有表单的标记,但是第一次点击进入地图时出现了这个错误:

Uncaught TypeError: Cannot set property 'value' of null

这是因为getElementByIdNULL,当我第二次点击时它匹配。我尝试了几个小时但没有得到它: - /

我的代码(部分内容):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">

<script src="https://maps.googleapis.com/maps/api/js"></script>
<script>

var map;
var marker;

function initJsMap() {
  var vienna = new google.maps.LatLng(48.2134567, 16.3789012);
  var mapOptions = {
    position: vienna,
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);

  google.maps.event.addListener(map, 'dblclick', function(event) {
    placeMarker(event.latLng);
  });

}

function placeMarker(location) {
  if (marker) {
    marker.setPosition(location);
  } else {
    var form = '<div id="form_canvasform">' +
                '<form method="POST" action="/addmap" name="form_canvas">' +
                '<div style="display:none;">' +
                '<input id="csrf_token" name="csrf_token" type="hidden" value="foo">' +
                '<input id="latitude" name="latitude" type="hidden" value="">' +
                '<input id="longitude" name="longitude" type="hidden" value=""></div>' +
                '<label for="link">link</label> <input id="link" name="link" type="text" value="">' +
                '<input type="submit" value="Go!">' +
                '</form>' +
                '</div>';
    infowindow = new google.maps.InfoWindow({
      content: form
    });
    marker = new google.maps.Marker({
      position: location,
      map: map,
      draggable: true
    });
    infowindow.open(map, marker);
    marker.addListener('click', function() {
      infowindow.open(map, marker);
    });
  }
  console.log("Latitude: " + location.lat());
  console.log("Longitude: " + location.lng());
  console.log(form);
  document.getElementById('latitude').value = location.lat();
  document.getElementById('longitude').value = location.lng();
}

</script>
</head>
<body onload="initJsMap()">
<div id="map-canvas" style="width:50%; height:600px;"></div>
</body>
</html>

表单内容由jinja2模板引擎(带烧瓶)生成。使用console.log(),我得到了正确的值。

[编辑]:

这是生成表单的jinja代码:

    var form = '<div id="form_canvasform">' +
      '<form method="POST" action="{{ request.path }}" name="form_canvas">' +
      '{{ form.hidden_tag() }}' +
      '{{ form.link.label }} {{ form.link }}' +
      '<br/>' +
      '<input type="submit" value="Go!">' +
      '</form>' +
      '</div>';

2 个答案:

答案 0 :(得分:1)

它与您在infoWindow正确打开之前尝试访问表单的隐藏元素有关。

编辑:这是一种方法,但它需要一些重新调整。

我正在使用String.replace来更改表单的值。我不知道是否有更简单的方法使用vanilla JavaScript(因为使用jQuery更容易),但它似乎有用。

var map;
var marker;

// regex to look for in HTML string
var latRe = /(<input id="latitude" name="latitude" type="hidden" value=")(.*)("><input id="longitude")/; 
var lngRe = /(<input id="longitude" name="longitude" type="hidden" value=\")(.*)(">.*<label)/;

function initJsMap () {
  var vienna = new google.maps.LatLng(48.2134567, 16.3789012);
  var mapOptions = {
    center: vienna, // 'center', not 'position'
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
  marker = new google.maps.Marker({  map: map, draggable: true });
  infowindow = new google.maps.InfoWindow();

  google.maps.event.addListener(map, 'dblclick', function(event) {
      placeMarker(event.latLng);
  });

  marker.addListener('click', function() {
      infowindow.open(map, marker);
  });
}

function placeMarker (location) {
    var form = 
      '<div id="form_canvasform">' +
      '<form method="POST" action="/addmap" name="form_canvas">' +
      '<div style="display:none;">' +
      '<input id="csrf_token" name="csrf_token" type="hidden" value="foo">' +
      '<input id="latitude" name="latitude" type="hidden" value="">' +
      '<input id="longitude" name="longitude" type="hidden" value=""></div>' +
      '<label for="link">link</label> <input id="link" name="link" type="text" value="">' +
      '<input type="submit" value="Go!">' +
      '</form>' +
      '</div>';
    // ugly: replace the values in the HTML string with the new values using regex
    form = form.replace(latRe, '$1' + location.lat() + '$3');
    form = form.replace(lngRe, '$1' + location.lng() + '$3');
    // set the new form
    infowindow.setContent(form);
    // set the new position of the marker
    marker.setPosition(location);
    // open infowindow
    google.maps.event.trigger(marker, 'click');
}

如果您需要有关我使用的正则表达式的信息,请查看此answer

DEMO

答案 1 :(得分:1)

当您使用字符串作为InfoWindow的内容时,InfoWindow中的元素在打开InfoWindow之前不可用(domready

但是你不能使用字符串作为内容,youz也可以直接使用DOMNode,无论是否已将其注入文档,该节点始终都是可访问的。

所以解决方案:根据form - 字符串创建一个DOMNode,并将其用作信息窗 - content

演示:(我已经为演示稍微修改了form,但它也适用于原始字符串)

&#13;
&#13;
function initJsMap() {
  var vienna      = new google.maps.LatLng(48.2134567, 16.3789012),
      mapOptions  = {
                      center: vienna,
                      zoom: 12,
                      disableDoubleClickZoom:true
                    },
      map         = new google.maps.Map(document.getElementById("map-canvas"),mapOptions),
      marker      = new google.maps.Marker({draggable: true}),
      infowindow  = new google.maps.InfoWindow({disableAutoPan:true}),
      form        = '<div id="form_canvasform">' +
                    '<form method="POST" action="/addmap" name="form_canvas">' +
                    '<input id="latitude" name="latitude"  value=""><br/>' +
                    '<input id="longitude" name="longitude"  value="">' +
                    '</form>' +
                    '</div>';
      node        = document.createElement('div'),
      content;
      
      node.innerHTML  = form;
      content         = node.firstChild
      infowindow.setContent(content);
      
      google.maps.event.addListener(map, 'dblclick', function(event) {
        marker.setOptions({position:event.latLng,map:map});
        infowindow.open(map,marker);
      });
      google.maps.event.addListener(marker, 'click', function(event) {
        marker.setPosition(event.latLng);
        infowindow.open(map,marker);
      });
      
      google.maps.event.addListener(marker, 'position_changed', function() {
        content.querySelector('input[name="latitude"]').value  = this.getPosition().lat();
        content.querySelector('input[name="longitude"]').value = this.getPosition().lng();
        if(infowindow.getMap()){
          infowindow.open(map,marker);
        }
      });
}
&#13;
html,body,#map-canvas{
  padding:0;
  margin:0;
  height:100%;
}
&#13;
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3&callback=initJsMap" async defer></script>
&#13;
&#13;
&#13;