jawj / OverlappingMarkerSpiderfier

Deals with overlapping markers in Google Maps JS API v3, Google Earth-style
http://blog.mackerron.com
836 stars 238 forks source link

Must wait for 'idle' event on map before calling markersNearAnyOtherMarker #151

Closed fredonweb closed 5 years ago

fredonweb commented 6 years ago

Hi,

I use this code for many months. All was ok. Since this week, my map doesn't work. I've this error code : "uncaught exception: Must wait for 'idle' event on map before calling markersNearAnyOtherMarker". I don't understand the problem.

Thanks for your help.

<!DOCTYPE html>
<html>
  <head>
    <title>GIE Dév. Foncier : Cartographie</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="author" content="fredonweb">
    <meta name="robots" content="noindex, nofollow, noarchive" />
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?key=XXXX&libraries=places"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/OverlappingMarkerSpiderfier/1.0.3/oms.min.js"></script>
    <script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js"></script>
  </head>

  <body>
    <div id="map-canvas"/></div>

       <div id="legend">
      <div id="logo">
          <i class="material-icons md-light">place</i>
      </div>
      <div id="search">
        <input id="pac-input" class="controls" type="text" placeholder="Rechercher...">
      </div>
      <div id="filter">
        <div class="title">
          <i class="titleIcon material-icons md-24">settings</i><i class="titleText">Filtrer les marqueurs</i><i id="filterBtn" class="iconBtn material-icons md-24" onclick="hideShowDown()">expand_less</i>
        </div>
        <div id="filterContent">
          <div>
            <p>Pour filtrer les marqueurs, indiquez la plage des identifiants prospection à afficher -identifiant minimum <b>et/ou</b> maximum-.</p>
          </div>
          <form>
            <div id="idminmax">
              <input type="text" class="controls" placeholder="Ex. 18010" name="idmin" id="idmin" />
              <span> / </span>
              <input type="text" class="controls" placeholder="Ex. 18050" name="idmax" id="idmax" />
              <input class="buttons" onclick="filterMarkers();" type=button name="filterButton" value="Filtrer" />
            </div>
            <div>
              <input type="checkbox" id="idCheckbox" name="idCheckbox" value="checkLabel">
              <label for="checkLabel">Afficher <b>uniquement</b> les prospections à valider</label>
            </div>
            <div>
              <input type="checkbox" id="emhCheckbox" name="emhCheckbox" value="checkLabelEmh" disabled>
              <label for="checkLabelEmh">Afficher le patrimoine</label>
            </div>
            <div>
              <input class="buttons, action" onclick="reinitializeMarkers();" type=button name="reinitializeButton" value="Réinitialiser" />
            </div>
          </form>
        </div>
      </div>

      <div id="markerInfos">
        <div class="title"><i class="titleIcon material-icons md">info_outline</i><i class="titleText">Aucun marqueur sélectionné</i></div>
        <div id="markerManuel">
          <p>Survolez un marqueur pour afficher ses informations.<br>Cliquez la carte pour créer un nouveau marqueur à l'endroit choisi. Les informations obtenues peuvent être modifiées ou complétées.<br>Pour enregistrer ce nouveau marqueur, copiez ses données et les enregistrer dans le tableau de données.</p>
        </div>
      </div>
  </body>

  <script type="text/javascript">
  /*
  // UI functions
  */

  // Copy the default markerInfos text
  var markerInfosChange = document.getElementById('markerInfos').innerHTML;

  // Get the element, add a click listener...
  document.getElementById("markerInfos").addEventListener("click", function(e) {
    if(e.target && e.target.matches("INPUT.noSelect")) {
      e.target.blur();
          console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");
      }
    if(e.target && e.target.matches("INPUT.select")) {
          console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");
      }
  });

  /*document.getElementById('emhCheckbox').onclick = function() {
    if ( this.checked ) {
      loadEmhMarkers();
    } else {
      setMapOnAll(null);
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(map);
      }
    }
  };*/

  // Set visible markers by category
  /*document.getElementById('idCheckbox1').onclick = function() {
    if ( this.checked ) {
      setMapOnAll(null);
      for (var i = 0; i < markers.length; i++) {
        if(markers[i].category == "Est Métropole Habitat") {
          markers[i].setMap(map);
        }
      }
    } else {
      var idmin = 1;
      var idmax = 200000;

      setMapOnAll(null);
      for (var i = 0; i < markers.length; i++) {
        if(markers[i].id >= idmin && markers[i].id <= idmax) {
          markers[i].setMap(map);
        }
      }
    }
  };*/

  // Hide show the filter part
  function hideShowDown() {
    var x = document.getElementById("filterContent");
    if (x.style.display === "none") {
        x.style.display = "block";
        document.getElementById("filterBtn").innerHTML = "expand_less";
    } else {
        x.style.display = "none";
        document.getElementById("filterBtn").innerHTML = "expand_more";
    }
  }

  // Hide show the bottom part
  function hideShowUp() {
    var x = document.getElementById("linkSheetAndHelp");
    if (x.style.display === "block") {
        x.style.display = "none";
        document.getElementById("copyrightBtn").innerHTML = "expand_less";
    } else {
        x.style.display = "block";
        document.getElementById("copyrightBtn").innerHTML = "expand_more";
    }
  }

  // Change icon after function done
  function changeIcon(i) {
    //if (i == 0) document.getElementById('iconCopyPaste').innerHTML = "assignment_turned_in";
    if (i == 1) document.getElementById('exportMarker').innerHTML = "cloud_done";
  }

  function noAccent(string) {
    var r = string;
        r = r.replace(new RegExp("[èéêë]", 'g'),"e");
        r = r.replace(new RegExp("[ìíîï]", 'g'),"i");
        r = r.replace(new RegExp("ç", 'g'),"c");
        r = r.replace(new RegExp("-", 'g'),"_");
        return r;
  }

  /*
  // Gmaps, variables
  */
  var map,
      lyon = {lat: 45.75, lng: 4.90},
      zoom = new Object(),
      markers = [],
      markersNew = [],
      infowindow = null,
      iwStyle = [],
      markerIcon = [
        { // [0] Current, color blue
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: '#00BCD4',
          fillOpacity: 1,
          scale: 4.5,
          strokeColor: '#0097A7',
          strokeWeight: 1.2
        },
        { // [1] Spiderfiable, color blue
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: '#00BCD4',
          fillOpacity: 1,
          scale: 4.5,
          strokeColor: '#00838F',
          strokeWeight: 2
        },
        { // [2] Spiderfied, color blue
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: '#80DEEA',
          fillOpacity: 1,
          scale: 4,
          strokeColor: '#0097A7',
          strokeWeight: 1
        },
        { // [3] New marker, color orange
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: '#FF8000',
          fillOpacity: 1,
          scale: 4.5,
          strokeColor: '#E65100',
          strokeWeight: 1.2
        },
        { // [4] Search result, red circle
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: 'white',
          fillOpacity: 1,
          scale: 5.5,
          strokeColor: 'red',
          strokeWeight: 2
        },
        { // [5] Current marker
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: '#E61875',
          fillOpacity: 1,
          scale: 6,
          strokeColor: 'white',
          strokeWeight: 2
        },
        { // [6]
          path: google.maps.SymbolPath.CIRCLE,
          fillColor: '#E61875',
          fillOpacity: 1,
          scale: 6,
          strokeColor: 'white',
          strokeWeight: 2
        }
      ],
      oms,
      j,
      k = 1,
      m = 0,
      n,
      previousMarker = null,
      previousMarkerIcon = markerIcon[0],
      markerCluster,
      exportMarker;

  /*
  // Gmaps, markers functions
  */
  // Infoswindow function
  function showInfowindow(marker, i, j) {
    marker.addListener('mouseover', (function(marker, i) {
      return function() {
        var content = j == 0 ? marker.id + ' - ' + marker.proprietairenom + '<p>' + marker.adresse + ', ' + marker.commune + '</p>':
        j == 1 ? 'Nouveau marqueur n°' + marker.id + '<p>' + marker.adresse + ', ' + marker.commune + '</p>':
        j == 2 ? 'Résultat de la recherche<p>' + marker.adresse + ', ' + marker.commune + '</p>':
        null;
        infowindow.setContent(content);
        infowindow.open(map, marker);
      }
    })(marker, i));
    marker.addListener('click', (function(marker, i) {
      return function() {
        console.log('Marqueur n°' + markers.indexOf(marker))
        iwStyle[0] = j == 0 ? 'filter_center_focus':
          j == 1 ? 'create':
          j == 2 ? 'search':
          null;
        iwStyle[1] = j == 0 ? '':
          j == 1 ? 'Nouveau marqueur n°':
          j == 2 ? '':
          null;
        iwStyle[2] = j == 0 ? '':
          j == 1 ? '<i id="exportMarker" class="iconBtn material-icons md" onclick="exportMarker(); changeIcon(1)">cloud_upload</i>':
          j == 2 ? '':
          null;
        iwStyle[3] = j == 0 ? 'readonly':
          j == 1 ? '':
          j == 2 ? '':
          null;
        iwStyle[4] = j == 0 ? '<input id="cadastre" class="markerInfosInput" type="text" value="' + marker.cadastre + '"/>':
          j == 1 ? '':
          j == 2 ? '':
          null;
        iwStyle[5] = j == 0 ? '':
          j == 1 ? '<input id="cadastre" class="markerInfosInput, select, text" type="text" placeholder="Références cadastrales"/>':
          j == 2 ? '':
          null;
        zoom = marker.getPosition();
        n = markers.indexOf(marker);
        var id =        '<div class="title">'+
                          '<i id="currentMarkerLocation" class="titleIcon material-icons md" onclick="zoomToMarker(zoom, n);">' + iwStyle[0] + '</i>'+
                          '<i class="titleText">' + iwStyle[1] + marker.id + '</i>'+
                          iwStyle[2] +
                        '</div>';
        var commune =   '<div class="markerInfosLink">'+
                          '<i class="markerInfosIcon material-icons md-24">location_city</i>'+
                          '<input id="commune" class="markerInfosInput, select, text" type="text" value="' + marker.commune + '"' + iwStyle[3] + '/>'+
                        '</div>';
        var adresse =   '<div class="markerInfosLink">'+
                          '<i class="markerInfosIcon material-icons md-24">location_city</i>'+
                          '<input id="adresse" class="markerInfosInput, select, text" type="text" value="' + marker.adresse + '"' + iwStyle[3] + '/>'+
                        '</div>';
        var cadastre =  '<div class="markerInfosLink">'+
                          '<a href="https://www.geoportail.gouv.fr/carte?c=' + marker.lng + ',' + marker.lat + '&amp;z=19&amp;l0=ORTHOIMAGERY.ORTHOPHOTOS::GEOPORTAIL:OGC:WMTS(0.80)&amp;l1=CADASTRALPARCELS.PARCELS::GEOPORTAIL:OGC:WMTS(1)&amp;permalink=yes" target="_blank">'+
                            '<i class="markerInfosIcon material-icons md-24">view_quilt</i>'+
                            iwStyle[4] +
                          '</a>'+
                          iwStyle[5] +
                          '<span class="tooltip">'+
                            '<i class="markerInfosIcon material-icons md-24">view_quilt</i>'+
                            '<i class="markerInfosIcon material-icons md-24">touch_app</i>'+
                            '<i class="markerInfosIcon material-icons md-24">forward</i>'+
                            '<i class="markerInfosIcon material-icons md-24">filter_hdr</i>'+
                          '</span>'+
                        '</div>';
        var gps =       '<div class="markerInfosLink" onclick="markerGpsCopy(0)" onmouseout="outFunc(0)">'+
                          '<i class="markerInfosIcon material-icons md-24">place</i>'+
                          '<input id="inputGps0" class="markerInfosInput, noSelect" type="text" value="' + marker.lat + ', ' + marker.lng + '" />'+
                          '<span class="tooltip" id="myTooltip0">'+
                            '<i class="markerInfosIcon material-icons md-24">touch_app</i>'+
                            '<i class="markerInfosIcon material-icons md-24">forward</i>'+
                            '<i class="markerInfosIcon material-icons md-24">content_copy</i>'+
                          '</span>'+
                        '</div>';
        var lat =       '<input id="lat" class="markerInfosInput, noSelect" type="hidden" value="' + marker.lat + '" />';
        var lng =       '<input id="lng" class="markerInfosInput, noSelect" type="hidden" value="' + marker.lng + '" />';
        if (marker.pluh !== "") {var pluh =
                        '<div class="markerInfosLink">'+
                          '<a href="http://pluh.grandlyon.com/plu.php?select_commune=' + noAccent(marker.commune).toUpperCase() + '" target="_blank">'+
                            '<i class="markerInfosIcon material-icons md-24">format_underline</i>'+
                            '<input id="commune" class="markerInfosInput" type="text" value="' + marker.pluh + '"' + iwStyle[3] + '/>'+
                          '</a>'+
                          '<span class="tooltip">'+
                            '<i class="markerInfosIcon material-icons md-24">touch_app</i>'+
                            '<i class="markerInfosIcon material-icons md-24">forward</i>'+
                            '<i class="markerInfosIcon material-icons md-24">format_underline</i>'+
                          '</span>'+
                        '</div>'
        } else {pluh = ""};
        if (marker.proprietairenom !== "") {var proprietairenom =
                        '<div class="markerInfosLink">'+
                          '<i class="markerInfosIcon material-icons md-24">face</i>'+
                          '<input id="commune" class="markerInfosInput" type="text" value="' + marker.proprietairenom + '"' + iwStyle[3] + '/>'+
                        '</div>'
        } else {proprietairenom = ""}
        if (marker.datecourrier !== "") {var datecourrier =
                        '<div class="markerInfosLink">'+
                          '<i class="markerInfosIcon material-icons md-24">mail</i>'+
                          '<input id="courrier0" class="markerInfosInput" type="text" value="Envoi le ' + marker.datecourrier + '"' + iwStyle[3] + '/>'+
                        '</div>'
        } else {datecourrier = ""}
        if (marker.relancecourrier !== "") {var relancecourrier =
                        '<div class="markerInfosLink">'+
                          '<i class="markerInfosIcon material-icons md-24">mail</i>'+
                          '<input id="courrier1" class="markerInfosInput" type="text" value="Relance le ' + marker.relancecourrier + '"' + iwStyle[3] + '/>'+
                        '</div>'
        } else {relancecourrier = ""}
        if (marker.fichecontact !== "") {var fichecontact =
                        '<div class="markerInfosLink"><a href="' + marker.fichecontact + '" target="_blank">'+
                          '<i class="markerInfosIcon material-icons md-24">description</i>'+
                          '<input id="ficheContact" class="markerInfosInput" type="text" value="Fiche contact"' + iwStyle[3] + '/>'+
                          '<span class="tooltip">'+
                            '<i class="markerInfosIcon material-icons md-24">visibility</i>'+
                          '</span>'+
                        '</div>'
        } else {fichecontact = ""}

        var content = j == 0 ? id + '<form class="inputDiv" id="formInit">' + commune + adresse + cadastre + gps + pluh + proprietairenom + datecourrier + relancecourrier + fichecontact + '</form>':
        j == 1 ? id + '<form class="inputDiv" id="formInit">' + commune + adresse + cadastre + gps + lat + lng + '</form>':
        j == 2 ? id + '<form class="inputDiv" id="formInit">' + commune + adresse + '</form>':
        null;

        $('#markerInfos').html(content);

        // Change icon of current marker visible in "markersInfos"
        if (j < 2) {
          markers[m].setIcon(previousMarkerIcon);
          console.log(' > Modification du marqueur n°' + m + ': Ok');
          m = markers.indexOf(marker);
          previousMarkerIcon = marker.getIcon();
          marker.setIcon(markerIcon[5]);
          console.log(' > Modification du marqueur n°' + m + ': Ok');
        }
      }
    })(marker, i));
    marker.addListener('dblclick', (function(marker, i) {
      return function() {
        map.setZoom(18);
        map.setCenter(marker.getPosition());
        if (j < 2) {
          setTimeout(function(){ marker.setIcon(markerIcon[5]); }, 500);
        }
      }
    })(marker, i));
  }

  // Set markers
  function loadMarkers() {
    var url = "https://spreadsheets.google.com/feeds/list/XXXXXX/od6/public/values?alt=json";
    var bounds = new google.maps.LatLngBounds();
    $.getJSON(url, function(data) {
      var entries = data.feed.entry;
      for (var i = 4; i < entries.length; i++) {
        var latLng = new google.maps.LatLng(entries[i]['gsx$lat']['$t'], entries[i]['gsx$lng']['$t']);
        if(entries[i]['gsx$lat']['$t'] == 0) {
          latLng = lyon;
        } else {
          var marker = new google.maps.Marker({
            position: latLng,
            map: map,
            id: entries[i]['gsx$id']['$t'],
            commune: entries[i]['gsx$commune']['$t'],
            adresse: entries[i]['gsx$adresse']['$t'],
            cadastre: entries[i]['gsx$cadastre']['$t'],
            lat: entries[i]['gsx$lat']['$t'],
            lng: entries[i]['gsx$lng']['$t'],
            pluh: entries[i]['gsx$pluh']['$t'],
            proprietairenom: entries[i]['gsx$proprietairenom']['$t'],
            datecourrier: entries[i]['gsx$datecourrier']['$t'],
            relancecourrier: entries[i]['gsx$relancecourrier']['$t'],
            fichecontact: entries[i]['gsx$fichecontact']['$t'],
          });
          markers.push(marker);
          oms.addMarker(marker);
          showInfowindow(marker, i, 0);
        }
        bounds.extend(latLng);
      }
      window.map = map;  // for debugging/exploratory use in console
      window.oms = oms;  // ditto
      map.fitBounds(bounds);
      markerCluster = new MarkerClusterer(map, markers,
        {
          imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m',
          gridSize: 40,
          maxZoom: 15,
        });
    });
  }

  // Add marker
  function addMarker(location) {
    // Géocode le nouvau marqueur : recherche de l'adresse
    var geocoder = new google.maps.Geocoder;
    geocoder.geocode({'location': location}, function(results, status) {
      if (status === 'OK') {
        if (results[1]) {
          // Find address from latLng
          var address_components = results[0].address_components;
          var components={};
          jQuery.each(address_components, function(k,v1) {jQuery.each(v1.types, function(k2, v2){components[v2]=v1.long_name});});
          if (components.street_number == null) components.street_number = '';
          var componentslat = results[0].geometry.location.lat().toFixed(8);
          var componentslng = results[0].geometry.location.lng().toFixed(8);

          var marker = new google.maps.Marker({
            position: location,
            animation: google.maps.Animation.DROP,
            map: map,
            icon: markerIcon[3],
            id: k,
            commune: components.locality,
            adresse: components.street_number + ' ' + components.route,
            cadastre: '',
            lat: componentslat,
            lng: componentslng,
            proprietairenom: '',
            datecourrier: '',
            relancecourrier: '',
            fichecontact: '',
          });
          markers.push(marker);
          showInfowindow(marker, marker.id, 1);
          k++;

          // Events on marker : add listener to delete marker
          marker.addListener('rightclick', function() {
            marker.setMap(null);
          });
        } else {
          window.alert('Aucune adresse trouvée');
        }
      } else {
        window.alert('Erreur de géocodage : ' + status);
      }
    });
  }

  // Create new marker into the spreadsheet
  function exportMarker() {
    var exportValue1 = document.getElementById('commune').value;
    var exportValue2 = document.getElementById('adresse').value;
    var exportValue3 = document.getElementById('cadastre').value;
    var exportValue4 = document.getElementById('lat').value;
    var exportValue5 = document.getElementById('lng').value;
    google.script.run.createNewMarker(exportValue1, exportValue2, exportValue3, exportValue4, exportValue5);
    console.log('Marqueur n°' + m + ' créé');
    console.log(' > ' + exportValue1 + '/' + exportValue2 + '/' + exportValue3 + '/' + exportValue4 + '/' + exportValue5);
    setTimeout(function() {reinitializeMarkers(1)}, 1200);
    setTimeout(function() {markers[m].setIcon(markerIcon[0])}, 4500);
    setTimeout(function() {markers[m].setIcon(markerIcon[5])}, 2000);
    console.log(' > Modification du marqueur n°' + m + ': Ok')
  }

  // Filter markers by Id
  function filterMarkers() {
    var idmin = document.getElementById("idmin").value;
    var idmax = document.getElementById("idmax").value;
    if (idmin == "") idmin = 1;
    if (idmax == "") idmax = 200000;

    setMapOnAll(null);

    for (var i = 0; i < markers.length; i++) {
      if(markers[i].id >= idmin && markers[i].id <= idmax) {
        markers[i].setMap(map);
        markerCluster.addMarker(markers[i]);
        if (markers[i].getMap == null)
          markers[i].marker.setMap(map);
      }
    }
  }

  // Filter markers "to validate"
  document.getElementById('idCheckbox').onclick = function() {
    if ( this.checked ) {
      var idmin = "à valider";
      var idmax = "à valider";

      setMapOnAll(null);

      for (var i = 0; i < markers.length; i++) {
        if (markers[i].id >= idmin && markers[i].id <= idmax) {
          markers[i].setMap(map);
          markerCluster.addMarker(markers[i]);
          if (markers[i].getMap == null)
            markers[i].marker.setMap(map);
        }
      }
    } else {
      setMapOnAll(null);
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(map);
        markerCluster.addMarker(markers[i]);
        if (markers[i].getMap == null)
          markers[i].marker.setMap(map);
      }
    }
  };

  // Sets the map on all markers in the array.
  function setMapOnAll(map) {
    //markerCluster.resetViewport();
    markerCluster.clearMarkers();
    for (var i = 0; i < markers.length; i++) {
      markers[i].setMap(map);
    }
  }

  // Clear the map
  function reinitializeMarkers(i) {
    setMapOnAll(null);
    markers = [];
    $('#idmin').val('');
    $('#idmax').val('');
    if (i !== 1) document.getElementById('markerInfos').innerHTML = markerInfosChange;
    loadMarkers(map);
  }

  // Zoom the current marker
  function zoomToMarker(zoom, n) {
    console.log('Zoom sur le marqueur n°' + m);
    map.setZoom(16);
    map.setCenter(zoom);
    setTimeout(function(){ markers[n].setIcon(markerIcon[5]); }, 500);
  }

  /*
  // Additionnel functions
  */
  // Copy to clipboard function
  function markerGpsCopy(i) {
    var inputGps = 'inputGps'+i;
    var myTooltip = 'myTooltip'+i;
    var copyText = document.getElementById(inputGps);
    copyText.select();
    document.execCommand('Copy');
    var tooltip = document.getElementById(myTooltip);
    tooltip.innerHTML = '<i class="markerInfosIcon material-icons md">done</i>';
  }

  // Tooltip copy and blur()
  function outFunc(i) {
    var myTooltip = 'myTooltip'+i;
    var tooltip = document.getElementById(myTooltip);
    tooltip.innerHTML = '<i class="markerInfosIcon material-icons md-24">touch_app</i><i class="markerInfosIcon material-icons md-24">forward</i><i class="markerInfosIcon material-icons md-24">content_copy</i>';
    this.blur()
  }

  /*
  // Gmaps, map functions
  */
  // Personnal map style
  function styleMap(map) {
    var styledMapType = new google.maps.StyledMapType(
      [
        {
          "featureType": "landscape.man_made",
          "elementType": "geometry.stroke",
          "stylers": [
            {
              "color": "#808080"
            },
            {
              "weight": 0.5
            }
          ]
        },
        {
          "featureType": "poi.business",
          "stylers": [
            {
              "visibility": "off"
            }
          ]
        },
        {
          "featureType": "poi.sports_complex",
          "stylers": [
            {
              "visibility": "off"
            }
          ]
        },
        {
          "featureType": "road.highway",
          "elementType": "geometry.fill",
          "stylers": [
            {
              "color": "#b7b7b7"
            }
          ]
        },
        {
          "featureType": "road.highway",
          "elementType": "geometry.stroke",
          "stylers": [
            {
              "color": "#888888"
            },
            {
              "weight": 0.5
            }
          ]
        },
        {
          "featureType": "road.highway",
          "elementType": "labels.icon",
          "stylers": [
            {
              "visibility": "off"
            }
          ]
        }
      ],
      {name: 'Adapté'}
    );
    map.mapTypes.set('styled_map', styledMapType);
    map.setMapTypeId('styled_map');
  }

  // Autocomplete search
  function searchBox() {
    // Create the search box and link it to the UI element.
    var input = document.getElementById('pac-input');
    var searchBox = new google.maps.places.SearchBox(input);
    //map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

    // Bias the SearchBox results towards current map's viewport.
    map.addListener('bounds_changed', function() {
      searchBox.setBounds(map.getBounds());
    });

    var searchMarkers = [];
    // Listen for the event fired when the user selects a prediction and retrieve
    // more details for that place.
    searchBox.addListener('places_changed', function() {
      var places = searchBox.getPlaces();
      if (places.length == 0) {
        return;
      }
      // Clear out the old searchMarkers.
      searchMarkers.forEach(function(marker) {
        marker.setMap(null);
      });
      searchMarkers = [];
      // For each place, get the icon, name and location.
      var bounds = new google.maps.LatLngBounds();
      places.forEach(function(place) {
        if (!place.geometry) {
          console.log("Aucun résultat trouvé pour cette recherche");
          return;
        }
        // Create a marker for each place
        for (var i = 0; i < places.length; i++) {
          console.log(places[0]);
          var marker = new google.maps.Marker({
            map: map,
            icon: markerIcon[4],
            id: 'Résultat de la recherche',
            adresse: place.address_components[0].long_name + ' ' + place.address_components[1].long_name,
            commune: place.address_components[2].long_name,
            position: place.geometry.location,
          });
          searchMarkers.push(marker);
          showInfowindow(marker, i, 2);
        }
        if (place.geometry.viewport) {
          // Only geocodes have viewport.
          bounds.union(place.geometry.viewport);
        } else {
          bounds.extend(place.geometry.location);
        }
      });
      map.fitBounds(bounds);
    });
  }

  // Initialize the map
  function initMap() {
    var mapOptions = {
      fullscreenControl: false,
      mapTypeControl: true,
      mapTypeControlOptions: {
        position: google.maps.ControlPosition.RIGHT_TOP,
        mapTypeIds: ['roadmap', 'satellite', 'styled_map']
      }
    };
    map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);

    // Add personnal map style
    styleMap(map);

    // Searchbox function
    searchBox();

    // Set the markers and the OverlappingMarkerSpiderfier function
    /*infowindow = new google.maps.InfoWindow();
    oms = new OverlappingMarkerSpiderfier(map,{
      markersWontMove: true,
      markersWontHide: true,
      basicFormatEvents: false,
      keepSpiderfied: true,
      ignoreMapClick: true,
      nearbyDistance: 0.001,
    });

    // Set markers
    loadMarkers(map);

    // Set the OverlappingMarkerSpiderfier markers style
    oms.addListener('format', function(marker, status) {
      var omsStyle = status == OverlappingMarkerSpiderfier.markerStatus.SPIDERFIED ? markerIcon[2] :
      status == OverlappingMarkerSpiderfier.markerStatus.SPIDERFIABLE ? markerIcon[1] :
      status == OverlappingMarkerSpiderfier.markerStatus.UNSPIDERFIABLE ? markerIcon[0] :
      null;
      marker.setIcon(omsStyle);
    });*/

    // Create the DIV center, filter and markerInfos
    //map.controls[google.maps.ControlPosition.TOP_CENTER].push(center);
    map.controls[google.maps.ControlPosition.LEFT_TOP].push(legend);

    // Add the listeners
    /*google.maps.event.addListener(map, 'click', function() {
      infowindow.close();
    });
    google.maps.event.addListener(map, 'rightclick', function(event) {
      addMarker(event.latLng);
    });*/
    google.maps.event.addListener(map, 'idle', function(event) {
      console.log('Map is now idle');
      //console.log(map.getCenter());
    });
  }

  google.maps.event.addDomListener(window, 'load', initMap);
  </script>
</html>
johnvanhulsen commented 5 years ago

Got the same issue... @fredonweb, do you have any updates?

tereg commented 5 years ago

I'm running into the same issue after months of it working just fine. I'm not using the markersNearAnyOtherMarker function explicitly in my code.

Here is where it is breaking for me in the marker-spiderfier.js file: p.markerProximityData = function() { var i1, i2, l, len1, len2, m, m1, m1Data, m2, m2Data, mData, n, nDist, pxSq, ref1, ref2; if (this.projHelper.getProjection() == null) { throw "Must wait for 'idle' event on map before calling markersNearAnyOtherMarker"; }

The error is coming from line 364.

@johnvanhulsen were you able to find a workaround?

fredonweb commented 5 years ago

Hello,

I find my problem : some of my gps informations were coding with wrong decimal separator (comma instead dot). Stupid mistake !

jawj commented 5 years ago

Glad you fixed it!

bavarianbytes commented 5 years ago

Get the same error on every 5th load. @johnvanhulsen did you find the problem or a solution?

vsemionov commented 4 years ago

I am getting the same error sporadically as well.

I am using the library as instructed by the documentation and I am not doing anything weird. My map data is not malformed. I am using OMS in combination with markerclustererplus. When the issue happens, the effect is that spiderfied markers are not labeled as such, and look like normal markers. There could be other effects as well.

I only managed to avoid the issue by initializing the OMS library inside the map idle event handler. However, the markers are then displayed incorrectly - on top of the marker clusters, which are supposed to hide the markers.

I tried downgrading the maps library to version 3.27, as the documentation states it is somewhat more reliable, but that didn't help.

Seaclick commented 4 years ago

Hello

Same issue here.

steve-vancouver commented 4 years ago

I'm getting this too. It is sporadic.

yongmin1983 commented 2 years ago

In my case, I loaded OverlappingMarkerSpiderfier() when Google Map is loaded by:

google.maps.event.addListenerOnce(map, 'idle', function() { // do something only the first time the map is loaded oms = new OverlappingMarkerSpiderfier(map, {}); });

google.maps.event.addListenerOnce() will make sure Google Map is loaded, the original answer is from: https://stackoverflow.com/a/7262773/8801901