I have a HERE Maps map displayed on a simple webpage with a multiselect dropdown and a couple of buttons. I'm using the contextmenu event to show a context menu on right-click, like so:
var map = new H.Map(
document.getElementById('mapContainer'),
maptypes.raster.normal.map,
{
zoom: 12,
center: { lat: -33.81, lng: 150.78 },
pixelRatio: window.devicePixelRatio || 1,
engineType: H.map.render.RenderEngine.EngineType.P2D
}
);
...
// an H.map.Polygon object we prepared earlier
polygonObject.addEventListener("contextmenu", handleContextMenu)
...
function handleContextMenu(evt) {
// Don't do anything if the map itself is right-clicked/long-pressed
if (evt.target === map) {
return;
}
if (evt.target instanceof H.map.Polygon) {
// Polygon-specific context menu items
evt.items.push(new H.util.ContextItem({ label: "ABC123" }));
evt.items.push(H.util.ContextItem.SEPARATOR);
evt.items.push(new H.util.ContextItem({ label: "Do something", callback: function () { doSomething(evt) } }));
}
}
This works fine, displays a context menu when a polygon object is right-clicked, and dismisses itself if somewhere else on the map is tapped. However, the context menu doesn't dismiss if the user clicks or interacts with another element on the page outside the map.
I wasn't able to find any documentation on how to achieve this behaviour, and the example that HERE Maps uses also doesn't dismiss the context menu if somewhere outside the map is clicked. Is there any way to dismiss the context menu on a map, either programmatically or automatically if another page element is interacted with?
It's a little bit hacky, but you can manually remove the context menu from the DOM by finding a div with the h_context_menu class in the page, and removing it. This may have some unintended side effects with the UI class, but seems to work OK from my brief testing.
Using JQuery:
$("div.h_context_menu").remove()
Using ES6:
document.querySelector("div.h_context_menu").remove()
Using vanilla JavaScript (compatible with Internet Explorer):
var el = document.querySelector("div.h_context_menu");
el.parentNode.removeChild(el);
Related
I have an embedded Google Maps V3, and gestureHandling defaults to "cooperative", which is great, because an infobox appears when clicking on a location cluster and it often needs scrolling. However, when the map view goes to full-screen, it returns to regular un-modified scrolling, capturing it before the infobox, rendering the infobox useless as I can't scroll in it anymore.
Is there any way to require cooperative scrolling in full-screen view, or re-capture the scrolling in the infobox first?
--- EDIT ---
Here's what's happening so far, simplified (it's across multiple model instances):
const theMap = new google.maps.Map($("#calendarMap"), {
zoom: 4,
center: {
lat: 39.82,
lng: -98.57
},
gestureHandling: "cooperative"
});
I'm trying to figure out the infoboxes, I'm not the best at reading through typescript, especially when it's a massive cluster of modules and models my seniors wrote.
I verified through console that the map is indeed in "cooperative" mode when in full-screen, I'm trying to mess with the infobox settings now.
Solved in a much better way. Code executes on creating the infobox, from the infobox model:
// this.div is the jQuery node that is this infobox
google.maps.event.addDomListener(this.div, "wheel", (e) => {
e.cancelBubble = true;
if (e.stopPropagation) {
e.stopPropagation();
}
});
I use Mapbox for a dynamic map on a website. It works really well except, I have a sidebar which list the pins with a little more description and an image. I want to make it so when I click on that sidebar, it would fire the click event of that marker on the map.
I used to do this all the time with Google Maps but now I'm stuck because even in the case that I can keep the instance of the marker, I cannot fire the click on it for some reason. It simply does nothing (maybe I need to re-bind the click event on it but I don't know how with mapbox)
I've encountered a few questions about this on Google and SO but none bring a real answer to that question except "keep the instance" which isn't always possible in some cases.
So basically I have a jQuery click event like this:
var marker = {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [lng, lat]
},
properties: {}
};
if (isPin) {
marker.properties = pinStyles.pin;
} else if (isWinery) {
marker.properties = pinStyles.winery;
} else {
marker.properties = pinStyles.user;
}
marker.properties.title = locationName;
marker.properties.description = pin.description;
var markerObject = L.mapbox.markerLayer(marker);
// Add to cluster
markers.addLayer(markerObject);
$('#marker_list a.marker_item:last').click(function() {
var geoJson = markerObject.getGeoJSON();
markerObject.fire('click'); // does nothing (openPopup makes "Uncaught TypeError: Object [object Object] has no method 'openPopup' " so I guess I'm not doing it right)
});
And I have this (click event for mapbox marker):
map.markerLayer.on('click', function(e) {
map.setView(e.layer.getLatLng(), map.getZoom());
});
Anyone has an idea about wether 1) fix the non-firing event OR 2) make an HTML link fire a mapbox marker click event OR .openPopup?
Thanks and have a nice day!
MapBox's marker layer is a collection of Leaflet markers. You can create an href to a function that look for a particular marker based on it's layer id.
map.markerLayer.getLayers() returns an array of layer objects that contain both a _leaflet_id and the method togglePopup.
Try matching your href call to the leaflet id and then fire map.markerLayer.getLayers()[i].togglePopup()
Let me know if this helps.
I am using OpenLayers to draw point features on a map with a cluster strategy.
strategy = new OpenLayers.Strategy.Cluster();
clusters = new OpenLayers.Layer.Vector("Clusters", {
strategies: [strategy],
styleMap: new OpenLayers.StyleMap({
"default": style,
"select": {
fillColor: "#ff0000",
strokeColor: "#ffbbbb"
}
})
});
[.......]
clusters.addFeatures(features);
I'm also using a SelectFeature to select the point features on my map.
select = new OpenLayers.Control.SelectFeature(
clusters, {
clickout: false,
toggle: false,
hover: false
}
);
map.addControl(select);
select.activate();
clusters.events.on({"featureselected": clickPoint});
When the user selects a clustered Feature a popup appears with a list of containing features to select. When he selects one of these the popup closes and the clustered feature remains selected.
Now comes the problem. I want to be able click on the clustered feature so the popup appears again. The only thing I'm able to do is to set toggle:true but then the feature gets unselected.
Is there a way to trigger an event when the user clicks on a selected Feature?
Thx in advance,
illy
To solve this problem I overwrite unselectAll as:
mySelectControl.unselectAll = function(options) {
OpenLayers.Control.SelectFeature.prototype.unselectAll.apply(
mySelectControl, arguments);
if (options && options.except) {
var myReselecteFeature = options.except;
... your code to show the popup of myReselecteFeature ...
}
};
You may be interested to look at this example:
http://jorix.github.com/OL-FeaturePopups/examples/feature-popups.html
It is a control that does this you do and a little more. For example keeps the selection after zooming using clusters.
NOTE: The default behavior is not what you are looking for but can be customized.
You could also unSelect your feature when the feature is selected. For me it was the shortest way to achieve for the click event for the feature. Also set the toggle flag to true to fire unselect event in case of clicks.
var pdfFeatureSelector = new OpenLayers.Control.SelectFeature(pdfLayer,{
clickout: true,
multiple: true,
toggle: true,
autoActivate: true,
onSelect: function(){
OpenLayers.Control.SelectFeature.prototype.unselectAll.apply(
pdfFeatureSelector);//unselect the feature when it is selected
}
});
I have an OpenLayers map and I want users to be able to draw a box by dragging their mouse (similar to this example here, select the "select feature (0 features selected)" option first) and obtain the boundaries of the drawn box.
I can manage to draw the box using smth like below, however it won't work when there are no features in the map or no features selected, and that will certainly be the case.
new OpenLayers.Control.SelectFeature(this._layers.osm, {
multiple: true,
box: true,
hover: false,
toggleKey: 'ctrlKey',
multipleKey: 'shiftKey',
onBeforeSelect: function() {
console.log(arguments);
}
})
Is there an easy way to accomplish this in OpenLayers or should I do the heavy lifting myself by tracking mouse drags and drawing/removing polygons accordingly?
Thanks.
Try to use "boxselectionend" event of SelectFeature control (requires 2.12)
But this event not returns boundaries or the selection made, only returns a layers array.
Another option is to create the Handler.Box externally, that is what I do in some cases as:
var mySelectFeature = OpenLayers.Control.SelectFeature(...);
var myHandlerBox = new OpenLayers.Handler.Box(
mySelectFeature, {
done: function(bounds) {
OpenLayers.Control.SelectFeature.prototype.selectBox.apply(
mySelectFeature, arguments);
... your code ...
}
},
{}
);
I have written a basic function to allow me to display a popup from a link outside the map. The functionality to open the popup is working fine, but I can't then close it.
Demo link: http://www.catchingtherain.com/bikestats/stations.php - click on links in left-hand tabbed panels.
Here's a bit more detail ...
A typical map has about 300 features on a vector layer 'stations' loaded from kml. These are activated onload using
select = new OpenLayers.Control.SelectFeature(stations);
stations.events.on({
"featureselected": onFeatureSelect,
"featureunselected": onFeatureUnselect
});
map.addLayer(stations);
map.addControl(select);
select.activate();
which works fine - I can open and close popups.
With my off-map links I am calling onclick="showMyPopup([x]) with [x] being an ID attribute loaded in from the kml. The showMyPopup function is
function showMyPopup(myID){
for(var a = 0; a < stations.features.length; a++){ //loop through all the features
var feature = stations.features[a];
if (feature.attributes.ID.value == myID) { //until it finds the one with the matching ID attribute
var content = "<h4>" + feature.attributes.name + "</h4>" + feature.attributes.description;
popup = new OpenLayers.Popup.FramedCloud("chicken",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(200,200),
content,
null, true, onPopupClose);
feature.popup = popup;
map.addPopup(popup);
}
}
}
This opens the correct popup from the stations layer as expected, and I can see the popup using the DOM inspector on the stations layer just as it would appear if loaded by clicking on the map feature, but there's then seemingly no way of closing it. The original features on the stations layer are working fine though (opening and closing).
Any help would be much appreciated (maybe there's a simpler way of tackling this?)
Thanks, James
PS and just in case, here's the onFeatureUnselect function ...
function onFeatureUnselect(event) {
var feature = event.feature;
if(feature.popup) {
map.removePopup(feature.popup);
feature.popup.destroy();
delete feature.popup;
}
}
Your on onPopupClose() function is:
function onPopupClose(evt) {
select.unselectAll();
}
When you select feature from map and click on popup's Close icon, then feature will be unselected, but popup is not closed yet. Then, onFeatureUnselect event is triggered, and popup is actually closed.
When you create popup by showMyPopup() function, you are not selecting it. onPopupClose() is called, but it doesn't close popup. onFeatureUnselect is not triggered.
I suggest to select feature in showMyPopup() function. featureselected event will be fired and popup is created by onFeatureSelect(), and user can close popup both with popup's Close icon and unselecting feature on map.
But alas, there's a possible bug (or unexpected behaviour) in OL, when you select feature with code and try to unselect it with clickout. It's described here: http://lists.osgeo.org/pipermail/openlayers-users/2012-September/026349.html One possible fix is to set SelectControl.handlers.feature.lastFeature manually.
function showMyPopup(myID){
for(var a = 0; a < stations.features.length; a++){ //loop through all the features
var feature = stations.features[a];
if (feature.attributes.ID.value == myID) { //until it finds the one with the matching ID attribute
// select is your SelectFeature control
select.select(feature);
// Fix for unselect bug
select.handlers.feature.lastFeature = feature;
break;
}
}
}
I take a look in the OpenLayers sources and there is in Popup.js something like that ...
...
var closePopup = callback || function(e) {
this.hide();
OpenLayers.Event.stop(e);
};
OpenLayers.Event.observe(this.closeDiv, "touchend",
OpenLayers.Function.bindAsEventListener(closePopup, this));
OpenLayers.Event.observe(this.closeDiv, "click",
OpenLayers.Function.bindAsEventListener(closePopup, this));
...
It seems to me if you add your own closePopup function you need to call the hide function in your code.