Polygon mouseover event position - javascript

There is a problem on my website. I need to capture "mousemove" event and after that change the position of hint window according to the position of cursor at the moment of event. Here is the code:
google.maps.event.addListener(country, 'mousemove', function(e) {
this.setOptions({fillOpacity: 1});
$('div.info-win').css('top', e.kb.clientY + 20 + 'px');
$('div.info-win').css('left', e.kb.clientX -50 + 'px');
$('div.info-win').show()
});
At first everything was ok, but soon browser started to show the error, that e.kb is not defined. I checked the event via console and realized that "e.kb" really does not exist. Instead there was "e.lb" so I changed it in my code. But now the problem is the same, and console shows me that "e.lb" does not exist. I cant explain it, but now the captured event has ".gb" property instead of ".lb". can someone help me and explain why this happens every week again , so I need always to check the name of event property?? this is the first time I see problem like that but at the same time I cannot find any solution!

The Google Maps MouseEvent doesn't give the screen X and Y values.
Instead, it seems to give only Latitude/Longitude of the mouse position.
Reference:
https://developers.google.com/maps/documentation/javascript/reference#MouseEvent
https://developers.google.com/maps/documentation/javascript/reference#PolyMouseEvent
You need to convert the Latitude/Longitude value to the screen mouse X/Y position which is explained here (similar question):
Get Position of Mouse Cursor on Mouseover of Google Maps V3 API Marker

The reason your map worked for a while and later started failing is that you are using undocumented properties of the MouseEvent object. As you discovered, these may change at any time.
Think about it: do kb and lb and gb sound like names you would use in your code to describe a mouse position? And would you change them willy-nilly like that? :-)
So why does Google use gibberish names like these, and why do they change them all the time?
In the original source code that their developers work on, of course they use readable and consistent names. But then they compile the code with a "minifier" that shortens the private variable/property/method names for faster loading. When they revise the source and recompile it, those short names get reassigned arbitrarily.
The three different property names you found over the weeks clearly all refer to the same object in the original source, but the minifier changed the name you see in the browser.
Never assume you can use a property or method you discover in your browser's developer tools - especially if it has a name that makes no sense. Check it first in the Maps API documentation, and if it's not there, don't use it.
See Seyong's answer for the details of how to change your code to use the documented methods.

Related

Zooming with anchor point in Openlayers programatically

I am working on a tabletop application where the touch input is represented as browser touchevents.
I need a zooming function in the OL which is, alike to ol.View.rotate and zoom with the zoom-center-point different from view-center-point. I know about the ol.interaction.MouseWheelZoom which does exactly the thing. However, I cannot use it. I've already tried the sequence of:
translate zoom-center-point to view-center-point
zoom
translate back
but this is a bit wierd considering the fact, that the implementation already exists for ol.interaction.MouseWheelZoom. Any idea?
At the end, I used part of the code for ol.interaction.PinchZoom. Source: https://github.com/openlayers/openlayers/blob/master/src/ol/interaction/pinchzoom.js

Why doesn't Leaflet provide the correct relatedTarget element on mouseout event?

I have a popup that is opened when the user hovers over a marker. Currently, the popup closes when the user hovers over it (for example, the user can't select the text inside the popup because it closes). I'm trying to fix this and I found a great way to do it, as you can see here:
http://jsfiddle.net/sowelie/3JbNY/
Although the solution works, the version of Leaflet that it is used in that fiddle is very old, so I updated the version of Leaflet to version 1.1.0 and that breaks the solution 90% of the times.
Here are two fiddles, the first one is the same as the working solution with old Leaflet but I added one console.log. The second one also has the console.log but it uses Leaflet 1.1.0.
Old one: http://jsfiddle.net/3JbNY/106/
New one: http://jsfiddle.net/3JbNY/105/
Notice that 100% of the times, the old solution always logs the correct relatedTarget element, which is the popup (of course, when you exit from the marker to the popup. If you exit from the marker to the map, it's not going to be the popup).
However, on the same solution with the new version of Leaflet, 90% of the times the relatedTarget is not the popup even if you're exiting to the popup all the time. This percentage is arbitrary, I didn't actually calculate it, what I mean is that if you try long enough, eventually the new solution will log the popup as the relatedTarget but that is very rare.
I want to know what is the correct behavior here. In my opinion, it should work as the old solution works: giving me the correct element where I'm exiting to, that way I can check if I'm exiting to the popup to not close it if that's the case. Why was that changed?
Is there any workaround to get the correct relatedTarget without relying on maybe the Leaflet team patching this? Or maybe a completely new solution that doesn't rely on relatedTarget?
I appreciate the help!
Edit: Title said mouseover but I meant mouseout.
Found the culprit. Some Leaflet classes have a CSS property called pointer-events set to none, check out what it does here. Because of this, the event on the popup was being ignored. So I fixed this by simply overriding the property to the auto value (in my case it was the leaflet-tooltip class, but they have a similar class to popups called leaflet-popup-tip-container).
Check out this issue on Leaflet's GitHub for more information: https://github.com/Leaflet/Leaflet/issues/5720.

Google Maps API and DynamicMapsEngineLayer: Loop Over Features in the Map

[Edit APRIL 2, 2014]
I want to emphasize something. My scenario does not have a user event driving it to trigger an event listener. I know the Maps API documentation shows how to get a feature's featureId property from a MapsEngineMouseEvent. But my scenario needs to get the feature's featureId programmatically.
I've also tried programmatically "faking" a click, but that doesn't work either. (It seems the event object can't be instantiated??)
My hunch is, the solution to this either 1) doesn't exist, 2) is deceptively simple, or 3) will only be discovered if a minimum level 8 mage rolls a natural 20 wisdom check..
[Original Problem Statement]
I have few scenarios in a customized Google Maps client where I need to loop over features in a DynamicMapsEngineLayer and modify their style traits. The DynamicMapsEngineLayer works by performing..
..client-side rendering of vector data, allowing the developer to
dynamically restyle the vector layer in response to user interactions
like hover and click.
The Maps API documentation describes how to restyle individual features using event listeners, which expose a special featureId value assigned by Google servers. But my scenario doesn't have user-driven events. For example, consider this hypothetical link:
http://www.acme-map.com/index.php?ZoomToAndHighlightFeatureWithId=12345
FeatureWithId is our own unique id, not Google's special
featureId, which we don't have at this point in the runtime.
I need the map to load right above a feature and highlight it by changing its style trait. It needs to do this programmatically when the map first loads, without any user interaction. If these vector features are truly rendered in the DOM, then surely there's a way, no matter how cryptic, to reach into the map's guts and access these objects?
Is there a way to loop over individual features in a DynamicMapsEngineLayer or get the featureId property without an event listener?
I may be missing something here, but if you already know the feature ID, you can restyle it directly without an event. Just call getFeatureStyle() directly and set the style as you wish:
var style = dynamicLayer.getFeatureStyle('1234');
style.strokeColor = '#FF0000';
style.iconImage = 'url(images/myIcon.png)';
And if you don't know the feature ID, but you do have some other attribute to query against, you can make a call out to the Maps Engine API to fetch it.

Javascript: call a function defined in a variable without eval

I'm writing a jQuery plugin that hooks to scroll and drag events, and rotates an element to point towards another element when a relevant event is triggered. Basically my plugin just detects the events, calculates the correct angle, and rotates the element accordingly using a third-party plugin. For a better explanation, you can see the demos of my plugin.
I don't want to force a certain rotation plugin to be used, so the rotation function's name may vary. At the moment I'm using eval to allow for custom function names, but I'd like to find another way of doing this. I've tried googling, but so far haven't found a solution.
So, is there a way to get around this? The rotation function's name is stored in settings.rotateFunction:
eval("$(this)." + settings.rotateFunction + "(angle)");
So far I've tried the "new Function(codeToEval)" method, but this for some reason breaks the use of $(this).
In Javascript object members (properties or functions) can be accessed using these two notations:
object.memberName
object["memberName"]
The second one is especially useful when member isn't known during design-time but rather during runtime. That's why you can call your rotate function this way:
$(this)[settings.rotateFunction](angle);
Use following syntax:
$(this)[settings.rotateFunction](angle);

Restrict an object to stay within another object

This is related to SVG, I have a large SVG object made of paths which stays static. With a press of a button, I can create another SVG object inside the larger object. The second object can be dragged with the mousedown.
PROBLEM:
Now I want to add a restriction so that the second object created cannot venture outside of the main object.
I tried using 'mouseup' for restriction but that does not work because the restriction is applied according to the cursor point on the second object, rather than the border of the second object.
Hope someone can help.
UPDATE:
#Phrogz : We have been trying to get Kevin's code to work but are struggling to get any results. We have a function attached to onmouseup to find out the intersected points of the object on the underneath path.
The function is suppose to give the results of the intersection & give an alert that the function has been exected. Its not giving anything in response, leading us to wonder whether the function is being executed at all.
Here is the main code:
var path=svgDoc.getElementById("path");
var str=intersectPathShape(path,DragTarget);
alert(str)
Phrogz, any thoughts on this?
You will need to use an intersection library like this one by Kevin Lindsey to detect when the paths overlap and prevent it. (He also provides demos of his code.)
Depending on how you implement your dragging, you may also need to check the bounding box of the two items to ensure that one is contained in the other (since dragging the child completely outside the parent would cause them not to intersect, but also not be a legal position).
The simplest code would be to store the last position of the child and return it to that position when an intersection is detected. Under fast dragging, though, this might cause the child to stop being dragged at a spot that is not actually touching. For a better user experience, you may want to try a binary search of intermediary offsets between the last known-good position and the current position to find the closest point along that path that is legal.
Kayote,
I think I answered this in another question. The short version is have a look at this github project:
https://github.com/thelonious/js-intersections
In particular, the loadShapes function in this file:
https://github.com/thelonious/js-intersections/blob/master/samples/IntersectionUtilities.js
You will need to instantiate a specific object per node type then pass those to Intersection.intersectShapes.
HTH,
Kevin

Categories

Resources