I'm having trouble getting AmMaps to execute a function when I click on a state. Here's my code. This line is not operating as I expect it to:
map.addListener("clickMapObject", function(event) {
When I shorten "clickMapObject" to just "click", the function works fine. But I need clickMapObject so the map will be able to tell me which state I've clicked on; if I use click it will only give me lat/long coordinates. What am I doing wrong?
Got a response back from AmCharts support:
Just to clarify, if the area/state/country does not have any actions
attach to it upon click (zoom, url, description, etc.) it does not
generate any click events.
In this case you need to explicitly make all such "inactive" areas
clickable by either setting "selectable" property for each area
individually or globally via AreasSettings:
http://docs.amcharts.com/3/javascriptmaps/MapArea#selectable
http://docs.amcharts.com/3/javascriptmaps/AreasSettings#selectable
The latter is probably more universal if you want all areas to
generate click event:
map.areasSettings = {
rollOverColor: "#009ce0"
selectable: true
};
I hope it helps.
And it did help. Adding selectable: true to my map.areasSettings object did the trick!
Related
The closest to my question are: Mapbox gl js - overlapping layers and mouse event handling, Mapbox add popup on hover (layer), close on mouseleave, but keep open on popup hover and How to ignore mouse events on a mapbox layer - but they don't answer it.
I have two layers, let's imagine one is for a country, and another is for a city. Both of them a handled like this:
// CountryLayer.js
map.on("mousemove", "country-layer", e => {
// show info about the country
featureProps = e.features[0] // display some notification from the props
...
// CityLayer.js
map.on("mousemove", "city-layer", e => {
// show info about the city
featureProps = e.features[0] // display some notification from the props
...
It's done in different components. But when I mouseover city-layer mapbox thinks that I'm still "mousemoving" on top of the country-layer as well, so I get two notifications from separate components, where I need only one - in that case from the city-layer cause it's on top of country-layer.
Handling the mousemove without layerId in one place is gonna be a mess and breaks all the good rules about programming. Creating external "event manager" which will track whether I'm hovering the city and if is so will remove mousemove event from country-layer - is complex. I didn't find any good alternatives. At least, I would be glad to disable pointer events for a layer like this:
map.on("mousemove", "city-layer", e => {
map.getLayer("country-layer").setStyle({ "pointer-events": false })
featureProps = e.features[0]
...
or something like this. Is it possible? Is there more adequate way around it?
e.originalEvent.stopPropagation(); does not work
It appears, that you can do e.originalEvent.preventDefault(); in the city-layer and add a check e.originalEvent.defaultPrevented in the country-layer from the example.
However, I have issues with z-index position of layers: map.moveLayer("city-layer", "country-layer"); or vice-vise doesn't actually change the way, event propogates, so for some reason my country-layer always come first, so when it checks for e.originalEvent.defaultPrevented, preventDefault() wasn't fired yet, so it comes always false.
But technically, this answers my question.
map.on can listen on multiple layers at once. With events like mousemove it returns features in reverse layer order (from "highest" to "lowest").
So the way to do this is:
map.on("mousemove", ["city-layer", "country-layer"], e => {
feature = e.features[0]
if (feature.layer.id === 'city-layer') {
// ...
} else {
// ...
}
});
I need to handle a zoom event in Open Layers 3.
The following is my code:
map_object = new ol.Map({
target: 'map',
controls: controls_list,
interactions: interactions_list,
overlays: [overlay],
layers: [OSM_raster, WFS_layer],
view: view
});
map_object.on("Zoom", function() {
console.log('Zooming...');
});
This code runs with no errors and shows a map, but there is no output to the console, suggesting this function isn't firing.
I have also tried:
map_object.on("drag", function() {
console.log('Dragging...');
});
And this too does nothing.
Any help as to how to handle map control events in OL3 would be much appreciated (particularly zooming!). Note I have tried 'zoom' as well as 'Zoom' for the type field of the on method.
Just to add to this, you can check variations of events available with 'propertychange', from what I am seeing, there is no explicit .on ('zoom', ...) but rather you can access 'resolution' and other properties as mentioned in previous comments:
map.getView().on('propertychange', function(e) {
switch (e.key) {
case 'resolution':
console.log(e.oldValue);
break;
}
});
try with moveend event. (see https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:moveend).
As mentioned by tonio, the way to listen on zoom change, which is called resolution change in openlayers terminology, is with
map.getView().on('change:resolution', (event) => {
console.log(event);
});
I find this is better (more succinct, less cruft) than listening on the general propertychange and verifying manually if the change concerns resolution.
This fires rapidly when using the mouse button so throttling it might be a good idea before launching any computation that waits for it to change.
Documentation for View
You can manage the moveend event...
We will need a global variable to alocate map’s view zoom level. I’ve
named it as currentZoomLevel.
There is available a moveend event. Let’s use it, and add a zoom level
check function..
In case of there’s a new zoom level, we trigger a zoomend event to
DOM’s document.
Finally we will need to add zoomend listener to the document element.
var = currentZoomLevel;
map.on('moveend', checknewzoom);
function checknewzoom(evt)
{
var newZoomLevel = map.getView().getZoom();
if (newZoomLevel != currentZoomLevel)
{
currentZoomLevel = newZoomLevel;
$(document).trigger("zoomend", zoomend_event);
}
}
$(document).on('zoomend', function () {
console.log("Zoom");
//Your code here
});
Source
So I'm having a problem generating my jVectorMap.
The map itself sits inside a very custom drop down menu that I have created and this is where I suspect the problem is.
When I mouseover my menu item to open up the drop down which contains the map the actual svg starts out with a forced dimension of 100px x 100px.
What I have tried to do a number of workarounds wher I call the "map.setSize()" either on the mouseclick event of the dropdown as well as the mouseover event of the container itself. The problem here is my dropdown is not subject to a click event but shows on the mouseover event. However, at the point of the mouseover event the actual container for the map hasn't loaded so I'm still stuck with a 100px x 100px svg.
To get around this I've put an event on the mouseover event of the container itself but this isn't great either as it then requires the user to move his mouse over the container before it actually shows the map, something I don't want to happen.
Is there a way of getting the map built inside a div which is invisible before my menu event occurs?
For an example of my problem I've created this at jsfiddle http://jsfiddle.net/AEup9/
You will notice that when you hover over the "Show Map" menu item (the only item) the drop down is blank except for the topic headers until you move the mouse over the actual drop down itself which then reloads the map. I then keep the map there by using my "loaded" variable created before my mouseover event and a force map.setSize() inside the same event:
var loaded = false;
$('#aamap').mouseover(function () {
if (!loaded) {
(function () {
map = new jvm.WorldMap({
map: 'za_mill_en',
container: $('#southafrica-map'),
backgroundColor: '#cbd9f5',
initial: {
fill: 'white'
},
series: {
regions: [{
attribute: 'stroke'
}]
}
});
loaded = true;
})();
}
map.setSize();
});
This is my rough work around but not what I really want as I want the map to show up first time.
Can anyone help me here?
Edit: I finally decided to NOT go ahead with using jvectormap due to this issue. Instead I opted to use jqvmap which is to some degree a fork of jvectormap, however the issues experienced with jvectormap were no longer a problem.
I met this issue as well.
To solve that problem we need to run an updateSize method on a map object when container of our map becomes visible. First, to get the map object we need to use this command:
$('#world-map').vectorMap('get', 'mapObject') and when execute updateSize on it, like:
var map = $('#world-map').vectorMap('get', 'mapObject');
map.updateSize();
or in a shorter form:
$('#world-map').vectorMap('get', 'mapObject').updateSize();
I am using a jQuery plugin for showing notifications.
so i can use something like this
show_notification("Successfully Saved your data","success");
we can use html content as message.
Now i want to perform some actions
ex.
show_notification("Do you want to save your data","success");
so this is a question to the user and user need to reply by clicking yes or no [both will be passed as html message]
what i need to do is when user clicks on yes/no i need to perform some actions.
i can use id or class to attach a click event,but i have many types of actions,and need to use very different id or class.
can i use a call back function or something like that ?
Please help me or give me your valuable suggestions .
Thank you.
Note : I know that it is not possible with current plugin and not talking about its functionalities ,i am just trying to modify the plugin.
In case there is no way to send a callback to your plugin, you would have to manually add the Yes/No-buttons to your message, and target them either by live delegates or by assigning a listener after the notification has been shown.
$(function() {
$('body').on('click', '.notification-yes', function() {
// yes-callback
});
$('body').on('click', '.notification-no', function() {
// no-callback
});
});
show_notification('Do you want to proceed? <button class="notification-yes">Yes</button> <button class="notification-no">No</button>', 'success');
If it is this plugin that you're using, you'll want your listeners to call closeNotification(). I realize that the syntax is not exactly the same, but that could be a versioning issue. It'd be easier to help you with the specifics if we knew the details of the plugin you're using.
You'll also need a way of knowing which notification was showing when the button was clicked. You could of course have unique button class names for different notifications. Another approach, if there is always just one notification showing at any given time, would be to have a small state object for the callback of interest. For instance:
var myNotifications = {
onYes: function() { },
onNo: function() { }
};
$(function() {
$('body').on('click', '.notification-yes', function() {
myNotifications.onYes();
closeNotification();
});
$('body').on('click', '.notification-no', function() {
myNotifications.onNo();
closeNotification();
});
});
function showCertainNotification() {
myNotifications.onYes = function() {
// specific callback for this notification.
};
show_notification('Confirm? <button class="notification-yes">Yes</button> <button class="notification-no">No</button>', 'success');
}
If there could be several notifications showing at any one time, a simple variable like that won't do. In that case you'd have to wrap your message in a container, the ID of which you could extract from your listener, and call a specific callback based on that, or passing that as a parameter. I won't go into detail here, seeing as the simple nature of show_notification implies an equally simple manner of close_notification. Since no ID's seems to be anywhere to be found, I'll assume that multiple active notifications are not supported.
A more appealing solution might have been to modify the plugin itself, rather than to work around it, so that you could pass callback functions directly to the plugin. Something like this:
show_notification({
message: 'Confirm',
type: 'success',
buttons: [
{ caption: 'Yes', click: function() { } },
{ caption: 'No', click: function() { } }
]
});
But of course, this is no way near possible to help you with, without first having a chance to look at what the plugin you're currently using looks like.
I'm having a problem with an image viewer I'm creating. Like the image below, the 'window' is where the image is shown and 'paging' is where the user can change the image. I've used this Jquery script to make the 'paging' fade in whenever the window is hovered over - It's hidden to start with. Although when the user hovers onto 'paging', it flickers. (Like shows then hides, etc.)
I suppose it's because the mouse isn't hovering over the 'window' anymore. Can anyone suggest how I can make 'paging' remain showing? Thanks for the help! :)
$(".window").hover(function() {
$(".paging").fadeIn('fast');
}, function() {
$(".paging").fadeOut('fast');
});
You can use .stop() here and include both in your .hover() selector, like this:
$(".window, .paging").hover(function() {
$(".paging").stop(true, true).fadeIn('fast');
}, function() {
$(".paging").stop(true, true).fadeOut('fast');
});
This way, when you leave to enter the child or back to the parent it stops the fade out and brings it right back, resulting in no visible action to the user.
You could try using mouseover and mouseout instead. I'm not sure that mouseout would react the same way hover does.
In fact, when you pass your mouse over the paging there is a magical thing that happens which is called "event bubbling": the "hover" event is passed to the container which is the parent of the "hovered" object, and so on until the "document" object.
So to solve your problem, you need to stop bubling, you can do it with "return false":
$(".paging").hover(function() {
return false;
}, function() {
return false;
});
(It's possible that in recent version of jquery you can replace the argument function(){return false;} by just false.)