Google Map Makers Sprite in OSX not displaying - iphone

I can't seem to get the my map markers to display when I use an image sprite on the iphone. They appear when I use the standard google map markers on iphone and when viewing the site in the desktop the sprite icons work fine.
Here is the code I use to create the markers, I am using Zepto but JQuery could as easily apply.
$.ajax({
dataType: 'jsonp',
url: myLocations.LocatorUrl,
timeout: 8000,
success: function(data) {
var infoWindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
$.each(data, function(index, item){
var data = item, pincolor,
latLng = new google.maps.LatLng(data.lat, data.lng);
var d = 'http://blah';
var pinImage = new google.maps.MarkerImage(d+"/assets/img/sprite.locator.png",
new google.maps.Size(24, 36),
new google.maps.Point(0,25),
new google.maps.Point(10, 34));
// Creating a marker and putting it on the map
var marker = new google.maps.Marker({
position: latLng,
map: map,
title: data.type,
icon: pinImage
});
bounds.extend(latLng); // Extend the Latlng bound method
var bubbleHtml = '<div class="bubble"><h2>'+item.type+'</h2><p>'+item.address+'</p></div>'; // Custom HTML for the bubble
(function(marker, data) {
// Attaching a click event to the current marker
google.maps.event.addListener(marker, "click", function(e) {
infoWindow.setContent(bubbleHtml);
infoWindow.open(map, marker);
});
markers.push(marker); // Push markers into an array so they can be removed
})(marker, data);
});
map.fitBounds(bounds); // Center based on values added to bounds
}, error: function(x, t, m) {
console.log('errors')
if(t==="timeout") {
alert("got timeout");
} else {
alert(t);
}
}
});

Got it. Turns out the images I was referencing were on localhost, when I swapped this to the actual IP address of my local machine it worked.

Related

Add interactivity to POIs from different tilesets

I'm working on Mapbox Studio Tutorial and practicing adding interactivity on POIs on map.
https://docs.mapbox.com/help/tutorials/add-points-pt-3/
map.on('click', (event) => {
// If the user clicked on one of your markers, get its information.
const features = map.queryRenderedFeatures(event.point, {
layers: ['layer1',"layer2","layer3"]
});
if (!features.length) {
return;
}
const feature = features[0];
/*
Create a popup, specify its options
and properties, and add it to the map.
*/
const popup = new mapboxgl.Popup({ offset: [0, -15] })
.setLngLat(feature.geometry.coordinates)
.setHTML(
`<h3>${feature.properties.title}</h3><p>${feature.properties.description}</p>`
)
.addTo(map);
});
The error I get is that the title of POIs from layer2 and layer3 is shown as "undefined" while layer1's title can be shown when clicking it on the map.
I think "undefined" comes because the title is not stored in the feature property but have no clear idea how to do that correctly.
I tried some codes I got from the internet such as below:
if (features.length > 0) {
// Loop feature and concatenate property as HTML strings
let propertiesHTML = '';
features.forEach(feature => {
Object.entries(feature.properties).forEach(([key, value]) => {
propertiesHTML += `<p><strong>${key}:</strong> ${value}</p>`;
});
});
// Create and add a popup
const popup = new mapboxgl.Popup({ offset: [0, -15] })
.setLngLat(features[0].geometry.coordinates)
.setHTML(propertiesHTML)
.addTo(map);
With code at least map is shown, but there is no interactive popup shown when I click it.

Leaflet: Layer check box state is reset every time the map moves or zooms

I have the following code which fetches some remote GeoJSON from an API and displays the results on a Leaflet map:
<script>
// Center the map
var map = L.map('map').setView([54.233669, -4.406027], 6);
// Attribution
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=REMOVED', {
attribution: 'Map © OpenStreetMap',
id: 'mapbox.streets'
}).addTo(map);
// Create an empty layergroup for the data
var LayerUTMGroundHazards = L.layerGroup();
var LayerUTMAirspace = L.layerGroup();
// Style the features
function setStyle(feature) {
return {
fillColor: feature.properties.fillColor,
color: feature.properties.strokeColor,
fillOpacity: feature.properties.fillOpacity,
opacity: feature.properties.strokeOpacity
};
}
// Build Guardian UTM
function getGuardianUTMdata() {
// Clear the current Layer content
LayerUTMGroundHazards.clearLayers();
LayerUTMAirspace.clearLayers();
// Define what we want to include
function FuncGroundHazards(feature) {
if (feature.properties.category === "groundHazard") return true
}
function FuncAirspace(feature) {
if (
(feature.properties.category === "airspace" || feature.properties.category === "airport")
&& feature.properties.detailedCategory !== "uk:frz"
) return true
}
// Build the layers
fetch("https://example.com/json?n=" + map.getBounds().getNorth() + "&e=" + map.getBounds().getEast() + "&s=" + map.getBounds().getSouth() + "&w=" + map.getBounds().getWest(), { headers: { 'Authorization': 'REMOVED', 'X-AA-DeviceId': 'mySite' } })
.then(function (responseGuardianUTM) { return responseGuardianUTM.json() })
.then(function (dataGuardianUTM) {
// Create Layer: Ground Hazards
var featuresUTMGroundHazards = L.geoJson(dataGuardianUTM, {
filter: FuncGroundHazards,
style: setStyle,
pointToLayer: function (feature, latlng) { return L.marker(latlng, { icon: L.icon({ iconUrl: feature.properties.iconUrl, iconSize: [25, 25], }), }) },
onEachFeature: function (feature, layer) { layer.bindPopup(feature.properties.name); },
});
// Add the L.GeoJSON instance to the empty layergroup
LayerUTMGroundHazards.addLayer(featuresUTMGroundHazards).addTo(map);
});
// other layers are here (removed from this example)
}
// Update the Guardian UTM layer if the map moves
map.on('dragend', function () { getGuardianUTMdata(); });
map.on('zoomend', function () { getGuardianUTMdata(); });
// Layer controls
var layerControl = new L.Control.Layers(null, {
'Airspace Restrictions': LayerUTMAirspace,
'Ground Hazards': LayerUTMGroundHazards
// other layers are here (removed from this example)
}).addTo(map);
</script>
The problem is that every time the map is moved or zoomed, all of the Layer checkboxes are reset to Checked again, regardless of how many were checked before the map moved. They do not honour / remember their state when the map moves.
Given my code above, how can I store or preserve the checkbox state for each of the multiple Layers that I have so they are not reset every time the map is moved?
EDIT:
Here is a working fiddle. Remove the checkbox from the 'Ground Hazards', then move or zoom the map, you will see how it puts a tick back in the box again
https://jsfiddle.net/hdwz1b6t/1/
You're (re-)adding LayerUTMGroundHazards every time. This line here...
// Add the L.GeoJSON instance to the empty layergroup
LayerUTMGroundHazards.addLayer(featuresUTMGroundHazards).addTo(map);
...is not only adding featureUTMGroundHazards to layerUTMGroundHazards, it's also (re-)adding layerUTMGroundHazards to the map.
And quoting from https://leafletjs.com/examples/layers-control/ :
The layers control is smart enough to detect what layers we’ve already added and have corresponding checkboxes and radioboxes set.
So when you do LayerUTMGroundHazards.addTo(map);, the checkboxes reset.

leaflet routing.control update when marker is moved

I am using leaflet and routing.control to show a route. I have it working fine, but I would like one of the markers to move with the users location using watch.position. But for now I a just trying to move the marker when I click a button. Again this works fine but when the marker moves I would like the route to update automatically. Its possible if you drag the marker so surely its possible when marker is moved in a different way? I can it if I remove the control and add a new one but this flickers too much. Any advice?
The code for the routing.control is
myroute = L.Routing.control({
waypoints: [
L.latLng(window.my_lat, window.my_lng),
L.latLng(window.job_p_lat, window.job_p_lng)
],show: true, units: 'imperial',
router: L.Routing.mapbox('API KEY HERE'),
createMarker: function(i, wp, nWps) {
if (i === 0 || i === nWps + 1) {
return mymarker = L.marker(wp.latLng, {
icon: redIcon
});
} else {
return job_start = L.marker(wp.latLng, {
icon: greenIcon
});
}
}
}).addTo(map);
and the code for moving the marker is
function movemarker() {
var lat = "52.410490";
var lng = "-1.575950";
var newLatLng = new L.LatLng(lat, lng);
mymarker.setLatLng(newLatLng);
// I assume I call something here?
}
Sorted, I did it with this, which removes first point and replaces it with new data
myroutewithout.spliceWaypoints(0, 1, newLatLng);

Leaflet & Mapbox: OpenPopup not working

I've an issue with the leaflet openPopup method.
showMap = function(elements) {
var jsonp = 'http://a.tiles.mapbox.com/v3/blahblahblah.jsonp';
var m = new L.Map("my_map").setView(new L.LatLng(51.5, -0.09), 15);
var geojsonLayer = new L.GeoJSON();
var PlaceIcon = L.Icon.extend({
iconSize: new L.Point(25, 41),
shadowSize: new L.Point(40, 35),
popupAnchor: new L.Point(0, -30)
});
var icon = new PlaceIcon(__HOME__ + '/images/leaflet/marker.png');
var marker;
for (var i = 0; i < elements.length; i++) {
var address = $("<div/>").html(elements[i].address).text();
var latlng = new L.LatLng(elements[i].latitude, elements[i].longitude);
marker = new L.Marker(latlng, {icon: icon}).bindPopup(address);
if (i == 0) {
marker.openPopup();
}
m.addLayer(geojsonLayer).addLayer(marker);
}
// Get metadata about the map from MapBox
wax.tilejson(jsonp, function(tilejson) {
m.addLayer(new wax.leaf.connector(tilejson));
});
}
When I click on a marker I have the popup open. But I would like to have the first popup open when the map is loaded. (and open other popups on markers click)
AnNy ideas ?
Put openPopup call after you add the marker to the map and you should be fine.
I'm assuming that when you click on a marker you see the popup but you're not getting the popup of the first marker to show automatically when the map is loaded?
First, it doesn't look like you're actually using GeoJSON so a GeoJSON layer isn't necessary (you can just use a FeatureLayer) but that shouldn't cause any issues. Whatever layer group you use you should only be adding it to the map once and then adding all child layers to the LayerGroup. You're currently adding the geojsonLayer multiple times in your "for" loop which you don't want to do.
Second, you have to call marker.openPopup() after the marker is added to the map.
Try changing your code around to looks something like this:
var layerGroup = new L.FeatureGroup();
layerGroup.addTo( m );
for (var i = 0; i < elements.length; i++) {
var address = $("<div/>").html(elements[i].address).text();
var latlng = new L.LatLng(elements[i].latitude, elements[i].longitude);
marker = new L.Marker(latlng, {icon: icon}).bindPopup(address);
//You don't add the marker directly to the map. The layerGroup has already
//been added to the map so it will take care of adding the marker to the map
layerGroup.addLayer( marker );
if (i == 0) {
marker.openPopup();
}
}
I had this issue and fixed it with adding a timeout right after I added the marker on the map.
marker.addTo(this.map).bindPopup('Info');
setTimeout(() => {
marker.openPopup();
}, 500);
I don't know why but on some page, I need to apply timeout. In any case it's my workaround, hope this works for some of you too.
First add your map then put openPopup():
L.marker([lat, long]).bindPopup('Your message').addTo(map).openPopup();

iPhone showing a blank infoWindow fro google maps

The info window shows ok on desktop, and if I set an alert to show the content it will show the correct html code. However, on the iPhone it will just pop a blank info window (No text within it).
Here is my code:
function showPOICategory(category) {
// Icons { ID, Image }
// Entry { Latitude, Longitude, Name, Description, iconID);
$.getJSON('ajax/poi.php?key=' + jQGMSettings.apiKey + '&c=' + category , function(data) {
$.each(data.poi, function(key, val) {
// Set current position marker
var $image = new google.maps.MarkerImage('/images/pois/'+data.icons[val.image],
// This marker is 20 pixels wide by 32 pixels tall.
new google.maps.Size(32, 37),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is the base of the flagpole at 0,32.
new google.maps.Point(16, 37)
);
var $marker = new google.maps.Marker({
title: val.title,
icon: $image,
clickable: true,
draggable: false,
position: new google.maps.LatLng(val.latitude, val.longitude),
animation: google.maps.Animation.DROP,
map: map
});
// Info Window
if( val.info == null ) {
var $infowindow = new google.maps.InfoWindow({
content: '<div><h1>' + val.title + '</h1>Prueba</div>'
});
} else {
var $infowindow = new google.maps.InfoWindow({
content: '<div style="color:#000000;"><h1 style="font-size:14px; font-family:Helvetica; padding:0px; margin:0px;">' + val.title + '</h1>' + val.info + 'Prueba</div>',
maxWidth: 200
});
}
var $listener = google.maps.event.addListener($marker, 'click', function() {
if( infoWindow != null ) {
infoWindow.close();
}
infoWindow = $infowindow;
infoWindow.open(map,$marker);
});
// Keep track of the marker to remove it ;)
pois.push({
marker: $marker,
listener: $listener
});
});
});
}
Anyone had this problem before? I'm going nutts to find out where the problem could be located.
OK I finally was able to solve my issue but not sure if it will help you. Are you using loadHTMLString method? if so and you aren't declaring a baseURL try declaring in the call
baseURL:[NSURL URLWithString:#"/"]