I am not a programmer or a developer. I am facing a problem that the google map infobox not display when they are in exact same location, (geocodezip) have a very good solution, however I don't know how to modify my code.
This is my code
(function ($) {
var settings;
var element;
var map;
var markers = new Array();
var markerCluster;
var clustersOnMap = new Array();
var clusterListener;
var methods = {
init: function (options) {
element = $(this);
var defaults = $.extend({
enableGeolocation: false,
pixelOffsetX : -145,
pixelOffsetY : -200
});
settings = $.extend({}, defaults, options);
google.maps.Map.prototype.setCenterWithOffset = function (latlng, offsetX, offsetY) {
var map = this;
var ov = new google.maps.OverlayView();
ov.onAdd = function () {
var proj = this.getProjection();
var aPoint = proj.fromLatLngToContainerPixel(latlng);
aPoint.x = aPoint.x + offsetX;
aPoint.y = aPoint.y + offsetY;
map.setCenter(proj.fromContainerPixelToLatLng(aPoint));
}
ov.draw = function () {
};
ov.setMap(this);
};
google.maps.visualRefresh = true;
google.maps.event.addDomListener(window, 'load', loadMap);
if (settings.filterForm && $(settings.filterForm).length !== 0) {
$(settings.filterForm).submit(function (e) {
var form = $(this);
var action = $(this).attr('action');
$.ajax({
type : 'GET',
url : action,
data : form.serialize(),
success: function (data) {
element.aviators_map('removeMarkers');
element.aviators_map('addMarkers', {
locations: eval(data.locations),
types : eval(data.types),
contents : eval(data.contents)
});
}
});
e.preventDefault();
});
}
if (options.callback) {
options.callback();
}
return $(this);
},
removeMarkers: function () {
for (i = 0; i < markers.length; i++) {
markers[i].infobox.close();
markers[i].marker.close();
markers[i].setMap(null);
}
markerCluster.clearMarkers();
$.each(clustersOnMap, function (index, cluster) {
cluster.cluster.close();
});
clusterListener.remove();
},
addMarkers: function (options) {
markers = new Array();
settings.locations = options.locations;
settings.contents = options.contents;
settings.types = options.types;
renderElements();
}
}
$.fn.aviators_map = function (method) {
// Method calling logic
if (methods[method]) {
return methods[ method ].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on Aviators Map');
}
};
function loadMap() {
var mapOptions = {
zoom : settings.zoom,
mapTypeId : google.maps.MapTypeId.ROADMAP,
scrollwheel : false,
draggable : true,
mapTypeControl : false,
panControl : false,
zoomControl : true,
zoomControlOptions: {
style : google.maps.ZoomControlStyle.SMALL,
position: google.maps.ControlPosition.LEFT_BOTTOM
}
};
if (settings.enableGeolocation) {
if (navigator.geolocation) {
browserSupportFlag = true;
navigator.geolocation.getCurrentPosition(function (position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(initialLocation);
}, function () {
mapOptions.center = new google.maps.LatLng(settings.center.latitude, settings.center.longitude);
});
} else {
browserSupportFlag = false;
mapOptions.center = new google.maps.LatLng(settings.center.latitude, settings.center.longitude);
}
} else {
mapOptions.center = new google.maps.LatLng(settings.center.latitude, settings.center.longitude);
}
map = new google.maps.Map($(element)[0], mapOptions);
var dragFlag = false;
var start = 0, end = 0;
function thisTouchStart(e) {
dragFlag = true;
start = e.touches[0].pageY;
}
function thisTouchEnd() {
dragFlag = false;
}
function thisTouchMove(e) {
if (!dragFlag) {
return
}
end = e.touches[0].pageY;
window.scrollBy(0, ( start - end ));
}
var el = $('#map')[0];
if (el.addEventListener) {
el.addEventListener('touchstart', thisTouchStart, true);
el.addEventListener('touchend', thisTouchEnd, true);
el.addEventListener('touchmove', thisTouchMove, true);
} else if (el.attachEvent){
el.attachEvent('touchstart', thisTouchStart);
el.attachEvent('touchend', thisTouchEnd);
el.attachEvent('touchmove', thisTouchMove);
}
google.maps.event.addListener(map, 'zoom_changed', function () {
$.each(markers, function (index, marker) {
marker.infobox.close();
marker.infobox.isOpen = false;
});
});
renderElements();
$('.infobox .close').live('click', function () {
$.each(markers, function (index, marker) {
marker.infobox.close();
marker.infobox.isOpen = false;
});
});
}
function isClusterOnMap(clustersOnMap, cluster) {
if (cluster === undefined) {
return false;
}
if (clustersOnMap.length == 0) {
return false;
}
var val = false;
$.each(clustersOnMap, function (index, cluster_on_map) {
if (cluster_on_map.getCenter() == cluster.getCenter()) {
val = cluster_on_map;
}
});
return val;
}
function addClusterOnMap(cluster) {
// Hide all cluster's markers
$.each(cluster.getMarkers(), (function () {
if (this.marker.isHidden == false) {
this.marker.isHidden = true;
this.marker.close();
}
}));
var newCluster = new InfoBox({
markers : cluster.getMarkers(),
draggable : true,
content : '<div class="clusterer"><div class="clusterer-inner">' + cluster.getMarkers().length + '</div></div>',
disableAutoPan : true,
pixelOffset : new google.maps.Size(-21, -21),
position : cluster.getCenter(),
closeBoxURL : "",
isHidden : false,
enableEventPropagation: true,
pane : "mapPane"
});
cluster.cluster = newCluster;
cluster.markers = cluster.getMarkers();
cluster.cluster.open(map, cluster.marker);
clustersOnMap.push(cluster);
}
function renderElements() {
$.each(settings.locations, function (index, location) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(location[0], location[1]),
map : map,
icon : settings.transparentMarkerImage
});
marker.infobox = new InfoBox({
content : settings.contents[index],
disableAutoPan : false,
maxWidth : 0,
pixelOffset : new google.maps.Size(settings.pixelOffsetX, settings.pixelOffsetY),
zIndex : null,
closeBoxURL : "",
infoBoxClearance : new google.maps.Size(1, 1),
position : new google.maps.LatLng(location[0], location[1]),
isHidden : false,
pane : "floatPane",
enableEventPropagation: false
});
marker.infobox.isOpen = false;
marker.marker = new InfoBox({
draggable : true,
content : '<div class="marker ' + settings.types[index] + '"><div class="marker-inner"></div></div>',
disableAutoPan : true,
pixelOffset : new google.maps.Size(-21, -58),
position : new google.maps.LatLng(location[0], location[1]),
closeBoxURL : "",
isHidden : false,
pane : "floatPane",
enableEventPropagation: true
});
marker.marker.isHidden = false;
marker.marker.open(map, marker);
markers.push(marker);
google.maps.event.addListener(marker, 'click', function (e) {
var curMarker = this;
$.each(markers, function (index, marker) {
// if marker is not the clicked marker, close the marker
if (marker !== curMarker) {
marker.infobox.close();
marker.infobox.isOpen = false;
}
});
if (curMarker.infobox.isOpen === false) {
curMarker.infobox.open(map, this);
curMarker.infobox.isOpen = true;
map.setCenterWithOffset(curMarker.getPosition(), 100, -120);
} else {
curMarker.infobox.close();
curMarker.infobox.isOpen = false;
}
});
});
markerCluster = new MarkerClusterer(map, markers, {
gridSize: 40,
styles: [
{
height : 42,
url : settings.transparentClusterImage,
width : 42,
textColor: 'transparent'
}
]
});
clustersOnMap = new Array();
clusterListener = google.maps.event.addListener(markerCluster, 'clusteringend', function (clusterer) {
var availableClusters = clusterer.getClusters();
var activeClusters = new Array();
$.each(availableClusters, function (index, cluster) {
if (cluster.getMarkers().length > 1) {
activeClusters.push(cluster);
}
});
$.each(availableClusters, function (index, cluster) {
if (cluster.getMarkers().length > 1) {
var val = isClusterOnMap(clustersOnMap, cluster);
if (val !== false) {
val.cluster.setContent('<div class="clusterer"><div class="clusterer-inner">' + cluster.getMarkers().length + '</div></div>');
val.markers = cluster.getMarkers();
$.each(cluster.getMarkers(), (function (index, marker) {
if (marker.marker.isHidden == false) {
marker.marker.isHidden = true;
marker.marker.close();
}
}));
} else {
addClusterOnMap(cluster);
}
} else {
// Show all markers without the cluster
$.each(cluster.getMarkers(), function (index, marker) {
if (marker.marker.isHidden == true) {
marker.marker.open(map, this);
marker.marker.isHidden = false;
}
});
// Remove old cluster
$.each(clustersOnMap, function (index, cluster_on_map) {
if (cluster !== undefined && cluster_on_map !== undefined) {
if (cluster_on_map.getCenter() == cluster.getCenter()) {
// Show all cluster's markers/
cluster_on_map.cluster.close();
clustersOnMap.splice(index, 1);
}
}
});
}
});
var newClustersOnMap = new Array();
$.each(clustersOnMap, function (index, clusterOnMap) {
var remove = true;
$.each(availableClusters, function (index2, availableCluster) {
if (availableCluster.getCenter() == clusterOnMap.getCenter()) {
remove = false;
}
});
if (!remove) {
newClustersOnMap.push(clusterOnMap);
} else {
clusterOnMap.cluster.close();
}
});
clustersOnMap = newClustersOnMap;
});
}
})(jQuery);
and This is geocodezip code
Google Maps Multiple markers with the exact same location Not working
Many Many Thanks
That solution is great, but I'd take a look at using the Overlapping Marker Spiderfier library to handle markers in the same location. You can use this in conjunction with the marker clusterer library, without any issues. This way you also don't lose the ability to see how many markers are actually in that same location - and it gives you a great UI in my opinion.
To use Overlapping Marker Spiderfier, include the script file before your main js file in your html. Then in your js, create an instance of the OverlappingMarkerSpiderfier object:
var oms = new OverlappingMarkerSpiderfier(map);
/*in your case I'd do this after you initialize the `map` object,
*and declare the `oms` globally, like you do with your other global objects
*/
Then when the markers are created, you want to add the marker to the oms object via the addMarker() method. So, in your case add the following line to the renderElements() function after the click event listener you declare for the marker:
oms.addMarker(marker);
Lastly, make sure to also clear the markers from the oms object when the removeMarkers() function in your code is called by adding the following to that function:
oms.clearMarkers();
Related
I think I'm doing something wrong in the variables or syntax... i don't know, help me to correct my code. (I'm using Leaflet for the map show)
Desired Behavior
The user should be able to see the BBOX entering the coordinates into the URL, for example:
.com/#013.0,052.0,013.5,052.5
I only care that the BBOX is shown, I don't care that the URL coordinates change when zooming or moving around the map.
My HTML
<!DOCTYPE html>
<html>
<header>
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="https://unpkg.com/leaflet#1.9.3/dist/leaflet.css"
integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
crossorigin=""
/>
<script
src="https://unpkg.com/leaflet#1.9.3/dist/leaflet.js"
integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
crossorigin=""
></script>
</header>
<body>
<div id="map"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="https://unpkg.com/leaflet#1.0.1/dist/leaflet.js"></script>
<script src="leaflet-hash.js"></script>
<script>
var map = L.map("map").setView([42, 12], 4);
// var hash = new L.hash(map);
var urlhash = window.location.hash.substring(1).split("/");
var boundingBox = "";
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 22,
minZoom: 1,
continuousWorld: false,
noWrap: false,
attribution:
'Data by OpenStreetMap, under ODbL.',
detectRetina: false,
}).addTo(map);
var bboxField = L.control({
position: "bottomleft",
});
bboxField.onAdd = function (map) {
//create div container for control
var div = L.DomUtil.create("div", "myButtonBar");
//prevent mouse events from propagating through to the map
L.DomEvent.disableClickPropagation(div);
//create custom radio buttons
div.innerHTML =
'BBOX (Left (LON) ,Bottom (LAT), Right (LON), Top (LAT), comma separated, with or without decimal point):<br><input type="text" id="bbox_field"/><button id="setDimensions">Display BBOX</button><button id="remove">Remove</button>';
return div;
};
bboxField.addTo(map);
$(".myButtonBar").css("font-weight", "bold");
if (urlhash[0] !== "") {
$("#bbox_field").val(urlhash[0]);
draw_bbox(urlhash[0]);
}
function draw_bbox(box) {
var myarray = box.split(",");
var bounds = [
[myarray[1], myarray[0]],
[myarray[3], myarray[2]],
];
boundingBox = L.rectangle(bounds, { color: "#ff7800", weight: 1 });
map.removeLayer(boundingBox);
boundingBox.addTo(map);
map.fitBounds(boundingBox.getBounds());
map.setZoom(map.getZoom() - 1);
}
$("#setDimensions").click(function () {
draw_bbox($("#bbox_field").val());
});
$("#bbox_field").keyup(function (event) {
if (event.keyCode === 13) {
$("#setDimensions").click();
}
});
// console.log(bbox)
$("#remove").click(function () {
map.removeLayer(boundingBox);
});
</script>
</body>
</html>
Leaflet Hash Plugin Code
(function(window) {
var HAS_HASHCHANGE = (function() {
var doc_mode = window.documentMode;
return ('onhashchange' in window) &&
(doc_mode === undefined || doc_mode > 7);
})();
L.hash = function(map) {
this.onHashChange = L.Util.bind(this.onHashChange, this);
if (map) {
this.init(map);
}
};
L.hash.parseHash = function(hash) {
if(hash.indexOf('#') === 0) {
hash = hash.substr(1);
}
var args = hash.split("/");
if (args.length == 3) {
var zoom = parseInt(args[0], 10),
lat = parseFloat(args[1]),
lon = parseFloat(args[2]);
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
return false;
} else {
return {
center: new L.LatLng(lat, lon),
zoom: zoom
};
}
} else {
return false;
}
};
L.hash.formatHash = function(map) {
var center = map.getCenter(),
zoom = map.getZoom(),
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
return "#" + [zoom,
center.lat.toFixed(precision),
center.lng.toFixed(precision)
].join("/");
},
L.hash.prototype = {
map: null,
lastHash: null,
parseHash: L.hash.parseHash,
formatHash: L.hash.formatHash,
init: function(map) {
this.map = map;
// reset the hash
this.lastHash = null;
this.onHashChange();
if (!this.isListening) {
this.startListening();
}
},
removeFrom: function(map) {
if (this.changeTimeout) {
clearTimeout(this.changeTimeout);
}
if (this.isListening) {
this.stopListening();
}
this.map = null;
},
onMapMove: function() {
// bail if we're moving the map (updating from a hash),
// or if the map is not yet loaded
if (this.movingMap || !this.map._loaded) {
return false;
}
var hash = this.formatHash(this.map);
if (this.lastHash != hash) {
location.replace(hash);
this.lastHash = hash;
}
},
movingMap: false,
update: function() {
var hash = location.hash;
if (hash === this.lastHash) {
return;
}
var parsed = this.parseHash(hash);
if (parsed) {
this.movingMap = true;
this.map.setView(parsed.center, parsed.zoom);
this.movingMap = false;
} else {
this.onMapMove(this.map);
}
},
// defer hash change updates every 100ms
changeDefer: 100,
changeTimeout: null,
onHashChange: function() {
// throttle calls to update() so that they only happen every
// `changeDefer` ms
if (!this.changeTimeout) {
var that = this;
this.changeTimeout = setTimeout(function() {
that.update();
that.changeTimeout = null;
}, this.changeDefer);
}
},
isListening: false,
hashChangeInterval: null,
startListening: function() {
this.map.on("moveend", this.onMapMove, this);
if (HAS_HASHCHANGE) {
L.DomEvent.addListener(window, "hashchange", this.onHashChange);
} else {
clearInterval(this.hashChangeInterval);
this.hashChangeInterval = setInterval(this.onHashChange, 50);
}
this.isListening = true;
},
stopListening: function() {
this.map.off("moveend", this.onMapMove, this);
if (HAS_HASHCHANGE) {
L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
} else {
clearInterval(this.hashChangeInterval);
}
this.isListening = false;
}
};
L.hash = function(map) {
return new L.hash(map);
};
L.map.prototype.addHash = function() {
this._hash = L.hash(this);
};
L.map.prototype.removeHash = function() {
this._hash.removeFrom();
};
})(window);
I am customizing the WordPress Geodirectory plugin's Google Maps API functionality to store the user set/selected map type, marker, and zoom level in local storage.
I have the user set map type and zoom level functionality working, but am struggling with implementing the selected map marker.
How would I go about storing and retrieving the selected map marker from local storage and displaying it on the map when the user clicks/taps back in the browser?
My existing custom code is included below:
const zoomChangeListener = google.maps.event.addListener(jQuery.goMap.map, 'zoom_changed', function (event) {
storeUserZoom();
});
loadUserZoom();
function storeUserZoom() {
let zoom = jQuery.goMap.map.getZoom();
localStorage.setItem( 'zoom', zoom);
// console.log('Storing zoom level: ' + zoom);
}
function loadUserZoom() {
let zoom = localStorage.getItem( 'zoom' );
if (localStorage.getItem( 'zoom' )) {
jQuery.goMap.map.setZoom(parseInt(zoom));
// console.log('Local storage zoom level: ' + zoom);
}
}
const mapTypeChangeListener = google.maps.event.addListener(jQuery.goMap.map, 'maptypeid_changed', function (event) {
storeUserMapType();
});
loadUserMapType();
function storeUserMapType() {
let mapType = jQuery.goMap.map.getMapTypeId();
localStorage.setItem( 'maptype', mapType);
// console.log('Map type changed: ' + mapType);
}
function loadUserMapType() {
let mapType = localStorage.getItem( 'maptype' );
if (localStorage.getItem( 'maptype' )) {
jQuery.goMap.map.setMapTypeId(mapType);
// console.log('Loading map type: ' + mapType);
}
}
function storeUserMarker(item, map_canvas) {
let markerId, markerTitle, markerIcon, markerPosition;
markerId = item.id;
markerTitle = item.title;
markerIcon = item.icon = {
url: item.icon,
// scaledSize: new google.maps.Size(resizeW, resizeH),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(0, 0)
};
// markerIcon = item.icon;
// console.log(markerIcon);
markerPosition = item.position;
localStorage.setItem( 'id', markerId );
localStorage.setItem( 'title', markerTitle );
localStorage.setItem( 'icon', JSON.stringify(markerIcon) );
localStorage.setItem( 'position', JSON.stringify(markerPosition));
}
function loadUserMarker(item, map_canvas) {
let markerId = localStorage.getItem( 'id' );
let markerTitle = localStorage.getItem( 'title' );
let markerIcon = JSON.parse(localStorage.getItem( 'icon' ));
let markerPosition = JSON.parse(localStorage.getItem( 'position' ));
if (localStorage.getItem( 'position' )) {
let marker = {
id: markerId,
title: markerTitle,
icon: markerIcon,
position: markerPosition,
visible: true,
clickable: true
};
gd_infowindow.open(jQuery.goMap.map, marker);
}
}
Geodirectory initMap function simplified with my additions marked as custom code
function initMap(map_options, marker) {
/** Custom code begin **/
google.maps.event.addListener(jQuery.goMap.map, 'tilesloaded', function() {
loadUserMarker(marker);
});
/** Custom code end **/
}
Geodirectory create_marker function with my additions marked as custom code
// create the marker and set up the event window
function create_marker(item, map_canvas) {
if (window.gdMaps == 'osm') {
return create_marker_osm(item, map_canvas);
}
var map_options = eval(map_canvas);
jQuery("#" + map_canvas).goMap();
gd_infowindow = (typeof google !== 'undefined' && typeof google.maps !== 'undefined') ? new google.maps.InfoWindow({
maxWidth: 200
}) : null;
if (item.lt && item.ln) {
var marker_id, title, icon, cs;
marker_id = item['m'];
title = geodir_htmlEscape(item['t']);
cs = item['cs'];
icon = item['icon'] ? item['icon'] : geodir_params.default_marker_icon;
iconW = item['w'] ? parseFloat(item['w']) : 0;
iconH = item['h'] ? parseFloat(item['h']) : 0;
iconMW = geodir_params.marker_max_width ? parseFloat(geodir_params.marker_max_width) : 0;
iconMH = geodir_params.marker_max_height ? parseFloat(geodir_params.marker_max_height) : 0;
/* Some svg files has dimensions with different unit */
if (geodir_params.resize_marker && ( iconW < iconMW || iconH < iconMH ) && icon.substr((icon.lastIndexOf('.')+1)).toLowerCase() == 'svg') {
iconW = iconW * 10;
iconH = iconH * 10;
}
if (geodir_params.resize_marker && iconW > 5 && iconH > 5 && ((iconMW > 5 && iconW > iconMW) || (iconMH > 5 && iconH > iconMH))) {
resizeW = iconW;
resizeH = iconH;
resize = false;
if (iconMH > 5 && resizeH > iconMH) {
_resizeH = iconMH;
_resizeW = Math.round(((_resizeH * resizeW) / resizeH) * 10) / 10;
resizeW = _resizeW;
resizeH = _resizeH;
resize = true;
}
if (iconMW > 5 && resizeW > iconMW) {
_resizeW = iconMW;
_resizeH = Math.round(((_resizeW * resizeH) / resizeW) * 10) / 10;
resizeW = _resizeW;
resizeH = _resizeH;
resize = true;
}
if (resize && resizeW > 5 && resizeH > 5) {
icon = {
url: icon,
scaledSize: new google.maps.Size(resizeW, resizeH),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point((Math.round(resizeW / 2)), resizeH)
};
}
}
var latlng = new google.maps.LatLng(item.lt, item.ln);
var marker = jQuery.goMap.createMarker({
id: marker_id,
title: title,
position: latlng,
visible: true,
clickable: true,
icon: icon,
label: cs,
zIndex: (item.zIndex ? item.zIndex : 0),
zIndexOrg: (item.zIndexOrg ? item.zIndexOrg : 0)
});
bounds.extend(latlng);
// Adding a click event to the marker
google.maps.event.addListener(marker, 'spider_click', function() { // 'click' => normal, 'spider_click' => Overlapping Marker Spiderfier
/** Custom code begin **/
storeUserMarker(marker);
/** Custom code end **/
var marker_url = map_options.map_marker_ajax_url;
is_zooming = true;
jQuery("#" + map_canvas).goMap();
var preview_query_str = '';
if (item.post_preview) {
preview_query_str = '&post_preview=' + item.post_preview;
}
marker_url = marker_url + '' + item.m;
post_data = marker_url.indexOf('?') === -1 ? '?' : '&';
post_data += '_wpnonce=' + map_options._wpnonce;
if (map_options.bubble_size) {
post_data += '&small=1';
}
if (map_options.map_marker_url_params) {
post_data += map_options.map_marker_url_params;
}
var loading = '<div id="map_loading"></div>';
gd_infowindow.open(jQuery.goMap.map, marker);
gd_infowindow.setContent(loading);
jQuery.ajax({
type: "GET",
url: marker_url + post_data,
cache: false,
dataType: "json",
error: function(xhr, error) {
alert(error);
},
success: function(response) {
jQuery("#" + map_canvas).goMap();
html = typeof response == 'object' && response.html ? geodir_htmlEscape(response.html) : '';
gd_infowindow.setContent(html);
gd_infowindow.open(jQuery.goMap.map, marker);
setTimeout(function() {
jQuery(document.body).trigger('geodir_map_infowindow_open', [{
map: 'google',
canvas: map_canvas,
content: html
}]);
}, 100);
// give the map 1 second to reposition before allowing it to reload
setTimeout(function() {
is_zooming = false;
}, 1000);
}
});
return;
});
// Overlapping Marker Spiderfier
jQuery.goMap.oms.addMarker(marker);
// Adding a visible_changed event to the marker
google.maps.event.addListener(marker, 'visible_changed', function() {
gd_infowindow.close(jQuery.goMap.map, marker);
});
return true;
} else {
//no lat & long, return no marker
return false;
}
}
The loadUserMarker(); function returns [object Object] in the console when executed.
The functionality can be tested on the staging site. Try clicking on a map marker, visiting the individual page, then return to the map with the browser back button.
Update
I am receiving the following error when trying to load the previously clicked/tapped map marker: Uncaught (in promise) TypeError: b.anchor.get is not a function. I know it relates to anchoring the info window to the map marker, but I am not sure how to correct it.
My storeUserMarker function has been updated to make item.icon into an object that includes the marker URL, origin, and anchor.
How would I go about getting the marker's anchor data so the info window can be displayed?
Can any one help me out ArcGIS JavaScript API NAVIGATION TOOLS to migrating from 3X to 4X (4.24) version. facing some of the challenges while doing the navigation tool migration.
please suggest me the solution.
var _prevExtent, _preExtent,
_currentvExtent, _extentHistory
require([
"esri/Map",
"esri/views/MapView",
"esri/core/watchUtils",
"dojo/dom-class",
"dojo/dom",
"dojo/on"
], function(Map, MapView, watchUtils, domClass, dom, on) {
_prevExtent = false;
_preExtent = null;
_currentExtent = null;
_extentHistory = [];
_extentHistoryIndx = 0;
_nextExtent = false;
var map = new Map({
basemap: "streets"
});
var view = new MapView({
container: "viewDiv",
map: map,
zoom: 4,
center: [15, 65] // longitude, latitude
});
watchUtils.whenTrue(view, "ready", function(){
initToolbar();
watchUtils.whenOnce(view, "extent", function(){
watchUtils.when(view, 'stationary', function(evt){
if(evt){
extentChangeHandler(view.extent);
}
});
});
});
function extentChangeHandler(evt) {
if(_prevExtent || _nextExtent){
_currentExtent = evt;
}else{
_preExtent = _currentExtent;
_currentExtent = evt;
_extentHistory.push({
preExtent: _preExtent,
currentExtent: _currentExtent
});
_extentHistoryIndx = _extentHistory.length - 1;
}
_prevExtent = _nextExtent = false;
extentHistoryChange();
}
function extentHistoryChange() {
if(_extentHistory.length === 0 || _extentHistoryIndx === 0 ){
domClass.add(dom.byId("zoomprev"), "disabled");
} else {
domClass.remove(dom.byId("zoomprev"), "disabled");
}
if(_extentHistory.length === 0 || _extentHistoryIndx === _extentHistory.length - 1){
domClass.add(dom.byId("zoomnext"), "disabled");
} else {
domClass.remove(dom.byId("zoomnext"), "disabled");
}
}
function initToolbar() {
on(dom.byId("zoomnext"), "click", function() {
_nextExtent = true;
_extentHistoryIndx++;
view.goTo(_extentHistory[_extentHistoryIndx].currentExtent);
});
on(dom.byId("zoomprev"), "click", function() {
if(_extentHistory[_extentHistoryIndx].preExtent){
_prevExtent = true;
view.goTo(_extentHistory[_extentHistoryIndx].preExtent);
_extentHistoryIndx--;
}
});
}
view.ui.add("tools", "top-right");
});
I am trying to use mapbox-gl with magento2 which uses requireJS. Mapbox-js seems to load but I have got a js error. I don't know if I missed requirejs config or if the error is due to my js code or if it's a bug ?
If someone can help me, thanks you.
mapbox-gl-js version: v1.0.0, v1.2.0 and v1.3.0
browser: Chrome
Steps to Trigger Behavior
1.Try to use mapbox into magento2 with requireJs
2.
3.
Link to Demonstration
No demonstration available sorry.
Expected Behavior
No error
Actual Behavior
Error in broswer console :
mapbox-gl-3.js:635 Uncaught TypeError: self.XMLHttpRequest is not a constructor at mapbox-gl-3.js:635 at dt (mapbox-gl-3.js:654) at Object.mt [as getArrayBuffer] (mapbox-gl-3.js:656) at Function.v.loadGlyphRange (mapbox-gl-3.js:11511) at mapbox-gl-3.js:11474 at mapbox-gl-3.js:9863 at Array.forEach () at Object.t.asyncAll (mapbox-gl-3.js:9862) at v.getGlyphs (mapbox-gl-3.js:11466) at i.getGlyphs (mapbox-gl-3.js:14227) (anonymous) # mapbox-gl-3.js:635 dt # mapbox-gl-3.js:654 mt # mapbox-gl-3.js:656 v.loadGlyphRange # mapbox-gl-3.js:11511 (anonymous) # mapbox-gl-3.js:11474 (anonymous) # mapbox-gl-3.js:9863 t.asyncAll # mapbox-gl-3.js:9862 v.getGlyphs # mapbox-gl-3.js:11466 i.getGlyphs # mapbox-gl-3.js:14227 du.receive # mapbox-gl-3.js:8739
At this moment, this is undefined, I guess it shouldn't but i don 't know how to fix it.
requirejs-config:
var config = { deps: [ [...] ], map: { '*': { [...] mapboxgl: "js/mapbox-gl-3", MapboxGeocoder: "js/mapbox-gl-geocoder.min", turf: "js/turf.min" } }, paths: { [...] }, config: { mixins: { [...] } }, shim : { 'mapbox-gl': { exports: 'mapbox-gl' }, 'leaflet-mapbox-gl': { deps: ['leaflet','mapbox-gl'] } } };
script JS :
`
require(['mapboxgl', 'MapboxGeocoder', 'turf'], function (mapboxgl, MapboxGeocoder, turf) {
// This will let you use the .remove() function later on
if (!('remove' in Element.prototype)) {
Element.prototype.remove = function () {
if (this.parentNode) {
this.parentNode.removeChild(this);
}
};
}
console.log('vahir2');
mapboxgl.accessToken = 'my_token_here';
// This adds the map
var map = new mapboxgl.Map({
// container id specified in the HTML
container: 'map',
// style URL
style: 'mapbox://styles/mapbox/streets-v9?optimize=true',
// initial position in [long, lat] format
center: [6.8541548, 46.4564862],
// initial zoom
zoom: 5,
scrollZoom: true
});
console.log('vahir3');
map.addControl(new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true,
showUserLocation: true
}));
map.addControl(new mapboxgl.NavigationControl());
//geocoder
var geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken, // Set the access token
mapboxgl: mapboxgl, // Set the mapbox-gl instance
marker: false, // Do not use the default marker style
bbox: [-5.7616150379, 41.9409963458, 19.6387755871, 55.208571099]
});
map.addControl(geocoder, 'top-left');
// This adds the data to the map
map.on('load', function (e) {
map.addSource('single-point', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [] // Notice that initially there are no features
}
});
map.addLayer({
id: 'point',
source: 'single-point',
type: 'circle',
paint: {
'circle-radius': 10,
'circle-color': '#007cbf',
'circle-stroke-width': 3,
'circle-stroke-color': '#fff'
}
});
geocoder.on('result', function (ev) {
var searchResult = ev.result.geometry;
map.getSource('single-point').setData(searchResult);
var options = {units: 'kilometers'};
stores.features.forEach(function (store) {
Object.defineProperty(store.properties, 'distance', {
value: turf.distance(searchResult, store.geometry, options),
writable: true,
enumerable: true,
configurable: true
});
});
stores.features.sort(function (a, b) {
if (a.properties.distance > b.properties.distance) {
return 1;
}
if (a.properties.distance < b.properties.distance) {
return -1;
}
// a must be equal to b
return 0;
});
var listings = document.getElementById('listings');
while (listings.firstChild) {
listings.removeChild(listings.firstChild);
}
buildLocationList(stores);
function sortLonLat(storeIdentifier) {
var lats = [stores.features[storeIdentifier].geometry.coordinates[1], searchResult.coordinates[1]];
var lons = [stores.features[storeIdentifier].geometry.coordinates[0], searchResult.coordinates[0]];
var sortedLons = lons.sort(function (a, b) {
if (a > b) {
return 1;
}
if (a.distance < b.distance) {
return -1;
}
return 0;
});
var sortedLats = lats.sort(function (a, b) {
if (a > b) {
return 1;
}
if (a.distance < b.distance) {
return -1;
}
return 0;
});
map.fitBounds([
[sortedLons[0], sortedLats[0]],
[sortedLons[1], sortedLats[1]]
], {
padding: 100
});
}
sortLonLat(0);
createPopUp(stores.features[0]);
});
// This is where your '.addLayer()' used to be, instead add only the source without styling a layer
map.addSource("places", {
"type": "geojson",
"data": stores,
tolerance: 3
});
// Initialize the list
buildLocationList(stores);
});
// This is where your interactions with the symbol layer used to be
// Now you have interactions with DOM markers instead
stores.features.forEach(function (marker, i) {
// Create an img element for the marker
var el = document.createElement('div');
el.id = "marker-" + i;
el.className = 'marker';
// Add markers to the map at all points
new mapboxgl.Marker(el, {
offset: [0, -23]
})
.setLngLat(marker.geometry.coordinates)
.addTo(map);
el.addEventListener('click', function (e) {
// 1. Fly to the point
flyToStore(marker);
// 2. Close all other popups and display popup for clicked store
createPopUp(marker);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
e.stopPropagation();
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
var listing = document.getElementById('listing-' + i);
listing.classList.add('active');
});
});
function flyToStore(currentFeature) {
map.flyTo({
center: currentFeature.geometry.coordinates,
zoom: 15
});
}
function createPopUp(currentFeature) {
var popUps = document.getElementsByClassName('mapboxgl-popup');
if (popUps[0]) popUps[0].remove();
var popup = new mapboxgl.Popup({
closeOnClick: false
})
.setLngLat(currentFeature.geometry.coordinates)
.setHTML('<h3>' + currentFeature.properties.name + '</h3>' +
'<h4>' + currentFeature.properties.desc + '</h4><img style="padding: 0% 0% 5% 6%;" src="/media/wysiwyg/store-locator/' + currentFeature.properties.image + '" />')
.addTo(map);
}
function buildLocationList(data) {
for (i = 0; i < data.features.length; i++) {
var currentFeature = data.features[i];
var prop = currentFeature.properties;
var listings = document.getElementById('listings');
var listing = listings.appendChild(document.createElement('div'));
listing.className = 'item';
listing.id = "listing-" + i;
if (prop.capsules == 1) {
var icon = listing.appendChild(document.createElement('img'));
icon.src = '/media/wysiwyg/store-locator/icon_capsule.png';
icon.style = 'float: right; height:18px;';
}
if (prop.machines == 1) {
var icon = listing.appendChild(document.createElement('img'));
icon.src = '/media/wysiwyg/store-locator/icon_machine.png';
icon.style = 'float: right; height:18px;';
}
var link = listing.appendChild(document.createElement('a'));
link.href = '#';
link.className = 'title';
link.dataPosition = i;
link.innerHTML = prop.name;
var details = listing.appendChild(document.createElement('div'));
details.innerHTML = prop.desc;
if (prop.distance) {
var roundedDistance = Math.round(prop.distance * 100) / 100;
details.innerHTML += '<p><strong>Distance : ' + roundedDistance + ' km</strong></p>';
}
link.addEventListener('click', function (e) {
// Update the currentFeature to the store associated with the clicked link
var clickedListing = data.features[this.dataPosition];
// 1. Fly to the point
flyToStore(clickedListing);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedListing);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
this.parentNode.classList.add('active');
});
}
}
});
`
Finally I found out that a tiers vendor overwritten "self".
I'm writing some code with the Google Maps API, it works fine in all browsers (FF, IE9, Chrome) but IE8 or below, I have assigned the map to a global variable called Map, which gets populated but when the addMarker function gets called the Map global is null in IE8, but the addMarker function does work when I call it from the locator function, I have included all these functions below.
var GoogleMaps = {};
var Map = null;
var init = (function () {
"use strict";
var MapType = null;
var ZoomLevel = null;
var ControlPos = null;
var ControlSize = null;
var myLatLong = null;
var Geocoder;
var result = null;
GoogleMaps.setup = function (options) {
myLatLong = new google.maps.LatLng(24.886436490787712, -70.26855468754);
if (google.loader.ClientLocation) {
myLatLong = new google.maps.LatLng(
google.loader.ClientLocation.latitude,
google.loader.ClientLocation.longitude);
} else if (options.Lat !== null && options.Long !== null) {
options.Location = new google.maps.LatLng(options.Lat, options.Long);
} else {
// Else centre to UK
options.Location = new google.maps.LatLng(52.961875, -1.419433);
}
if (options.MapType.toUpperCase() === 'ROADMAP') {
MapType = google.maps.MapTypeId.ROADMAP;
} else if (options.MapType.toUpperCase() === 'TERRAIN') {
MapType = google.maps.MapTypeId.TERRAIN;
} else if (options.MapType.toUpperCase() === 'HYBRID') {
MapType = google.maps.MapTypeId.HYBRID;
} else {
MapType = google.maps.MapTypeId.SATELLITE;
}
// Check zoom level, if not set then set to zoom level 8.
if (options.ZoomLevel) {
ZoomLevel = options.ZoomLevel;
} else {
ZoomLevel = 8;
}
var mapOptions = {
center: myLatLong,
zoom: ZoomLevel,
mapTypeId: MapType
};
var mapDiv = document.getElementById('canvas');
// Map gets initiated here
window.Map = new google.maps.Map(mapDiv, mapOptions);
delete options.MapType;
delete options.Lat;
delete options.Long;
delete options.ZoomLevel;
};
GoogleMaps.addMarker = function (options) {
var Location = null;
var Animation = null;
var Title = null;
var Draggable = null;
var Content = null;
var InfoWindow = null;
var Flat = null;
var Clickable = null;
if (options.lat !== null && options.long !== null) {
Location = new google.maps.LatLng(options.lat, options.long);
;
} else {
Location = myLatLong;
}
if (typeof(options.position) !== "undefined") {
Location = options.position;
}
if (options.animation.toUpperCase() === 'BOUNCE') {
Animation = google.maps.Animation.BOUNCE;
} else if (options.animation.toUpperCase() === 'DROP') {
Animation = google.maps.Animation.DROP;
} else {
Animation = google.maps.Animation.NONE;
}
if (options.draggable !== null && options.draggable === 'true') {
Draggable = true;
} else {
Draggable = false;
}
if (options.title !== null) {
Title = options.title;
} else {
Title = null;
}
if (options.content !== null) {
Content = options.content;
InfoWindow = new google.maps.InfoWindow({
content: Content
});
}
if (options.flat !== null && options.flat === 'true') {
Flat = true;
} else {
Flat = false;
}
if (options.clickable !== null && options.clickable === 'true') {
Clickable = true;
} else {
Clickable = false;
}
// Gets used in this section
var Marker = new google.maps.Marker({
position: Location,
map: window.Map,
animation: Animation,
draggable: Draggable,
title: Title,
flat: Flat,
clickable: Clickable,
zIndex: 1
});
// and sets map here
Marker.setMap(window.Map);
if (options.content !== null) {
google.maps.event.addListener(Marker, 'click', function (e) {
InfoWindow.open(window.Map, this);
google.maps.event.addListener(window.Map, 'click', function (e) {
InfoWindow.close(window.Map, window.Marker);
});
});
}
google.maps.event.addListener(Marker, 'dragend', function (e) {
});
delete options.lat;
delete options.long;
delete options.animation;
delete options.title;
delete options.content;
delete options.flat;
delete options.draggable;
delete options.clickable;
};
GoogleMaps.Locator = function (result) {
var address = null;
Geocoder = new google.maps.Geocoder();
address = result;
Geocoder.geocode({ 'address': address }, function (response, status) {
if (status === google.maps.GeocoderStatus.OK) {
window.Map.setCenter(response[0].geometry.location);
var Location = new google.maps.LatLng(response[0].geometry.location.Xa, response[0].geometry.location.Ya);
var markerOptions = {
animation: "drop",
draggable: "true",
content: 'Hello World!',
title: "Hello",
position: Location
};
GoogleMaps.addMarker(markerOptions);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
};
Below is how I am calling the functions:
var markerOptions = {
lat: 52.48278,
long: -0.892089,
animation: "drop",
draggable: "true",
content: 'Hello World!',
title: "Click Me"
};
google.maps.event.addDomListener(window, 'load', function () { GoogleMaps.setMarker(markerOptions) });
google.maps.event.addDomListener(window, 'load', function () { GoogleMaps.Locator('London') });
Thanks for any help.
I resolved the problem like this.
<meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7; IE=EmulateIE9″/>
Try changing this line in your setup
window.Map = new google.maps.Map(mapDiv, mapOptions);
to just
Map = new google.maps.Map(mapDiv, mapOptions);
This way you accessing the global variable declared.
when is GoogleMaps.setup called? Right now it looks like depending on the browser it can be called after functions attached by
google.maps.event.addDomListener(window, 'load', function () { ... });
and that's why map is not set when you call addMarker, but is already initialized when you receive callback from
Geocoder.geocode(...)
To fix this make sure that GoogleMaps.setup is called before addMarker.
IE8 has always meant trouble. :-) Try adding the following meta tag at the beginning of your <head> section:
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
Description here:
http://blogs.msdn.com/b/ie/archive/2008/06/10/introducing-ie-emulateie7.aspx