Highlight Google maps polyline when mouseover a placemark link - ruby-on-rails

I have tried to find this online but without much luck. Stackoverflow also does not seem to have a similar question-solution. This is the closest comparison I found:
http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/2121de2422cf5053?pli=1
But this person's live page doesn't look like they made it very far (they only have Jan 2010 working on their map)...but same idea as what I want to do. I don't know how to implement the given solution, either, since I will have hundreds of polylines and do not want to create a global variable for each one of them...
What I would like to do is "cluster" somehow a placemark with a set of polylines starting / ending from that marker. I will then have a link in a sidebar / menu off-map to this placemark, and I would like that when the user hovers / mouseovers the link to the placemark, the polylines associated with the placemark change their opacity (i.e. highlight). I think my questions are:
How can I reference a polyline that has already been created? How do I figure out its handle?
Can I somehow change a polyline's properties using the fact that it "passes through" my marker? (i.e. aSel.onmouseover("all polylines touching this object have opacity = 1"))
Any suggestions on how to modify the gmaps4rails.base.js file's "create polyline" function to do this? https://github.com/apneadiving/Google-Maps-for-Rails/blob/master/app/assets/javascripts/gmaps4rails/gmaps4rails.base.js.coffee
I have the feeling then my problem would become "how do I know the handler for the link / placemark when creating polylines?" if I try this method...
I am currently using Rails and the gmaps4rails plugin to try this, but am open to other elegant suggestions / solutions.
Thanks for your help!
==========================================
This is the code for what I've tried so far, following apneadiving's suggestion below (I am not a Rails, javascript, Coffeescript, or Maps expert...):
In gmaps4rails.base.js, in the createSidebar function, added the second line:
aSel.onclick = #sidebar_element_handler(currentMap, marker_container.serviceObject, 'click')
aSel.onmouseover = #sidebar_highlight_paths(currentMap, marker_container.serviceObject)
Then defined:
sidebar_highlight_paths : (currentMap, marker) ->
return () ->
for polyline in Gmaps.map.polylines
points = polyline.serviceObject.latLngs.getArray()[0].getArray()
if (#sidebar_intersect(points, marker.position))
#polyline.setOptions({strokeOpacity: 1.0})
sidebar_intersect : (a, b) ->
[a, b] = [b, a] if a.length > b.length
value for value in a when value in b
The intersect function is based off of the response here:
Coffeescript: Array element matches another array
Now I get no change in opacity and this error in my Chrome javascript console whenever I mouseover a link:
Uncaught TypeError: Object javascript:void(0); has no method 'sidebar_intersect'
Gmaps4Rails.Gmaps4Rails.sidebar_highlight_pathsgmaps4rails.base.js:434
Resource interpreted as Image but transferred with MIME type text/html: "http://maps.googleapis.com/maps/gen_204?ev=api_viewport&cad=src:apiv3,ts:1336420051554".
Line 434 (for the no method error above) is:
if #map_options.auto_adjust
#from markers
#extendBoundsWithMarkers()
->line 432<-
#from polylines:
for polyline in #polylines ->line 434<-
polyline_points = polyline.serviceObject.latLngs.getArray()[0].getArray()
for point in polyline_points
#boundsObject.extend point
Which has nothing to do with my new function, sidebar_intersect, so I am confused! Also, I am ignoring the Resource Interpreted error right now since it seems much more common...
Thanks for your tips, aneadiving, and I appreciate anyone else who can shed some light on my new errors...
=============================
Okay, figured this out--thanks apneadiving for your tips! For future reference (if this actually helps anyone), I basically added these two lines (onmouseover and onmouseout) to createSidebar in gmaps4rails.base.js.coffee:
aSel.onclick = #sidebar_element_handler(currentMap, marker_container.serviceObject, 'click')
aSel.onmouseover = #sidebar_highlight_paths(currentMap, marker_container.serviceObject)
aSel.onmouseout = #sidebar_reset_paths(currentMap, marker_container.serviceObject)
li.appendChild(aSel)
ul.appendChild(li)
Then:
sidebar_highlight_paths : (currentMap, marker) ->
return () ->
for polyline in Gmaps.map.polylines
b = polyline.serviceObject.latLngs.getArray()[0].getArray()
for latlng in b
if (marker.position.equals(latlng))
polyline.serviceObject.setOptions({strokeOpacity: 1})
sidebar_reset_paths : (currentMap, marker) ->
return () ->
for polyline in Gmaps.map.polylines
polyline.serviceObject.setOptions({strokeOpacity: 0.1}

Okay, figured this out--thanks apneadiving for your tips! For future reference (if this actually helps anyone), I basically added these two lines (onmouseover and onmouseout) to createSidebar in gmaps4rails.base.js.coffee:
aSel.onclick = #sidebar_element_handler(currentMap,marker_container.serviceObject, 'click')
aSel.onmouseover = #sidebar_highlight_paths(currentMap,marker_container.serviceObject)
aSel.onmouseout = #sidebar_reset_paths(currentMap,marker_container.serviceObject)
li.appendChild(aSel)
ul.appendChild(li)
Then:
sidebar_highlight_paths : (currentMap, marker) ->
return () ->
for polyline in Gmaps.map.polylines
b = polyline.serviceObject.latLngs.getArray()[0].getArray()
for latlng in b
if (marker.position.equals(latlng))
polyline.serviceObject.setOptions({strokeOpacity: 1})
sidebar_reset_paths : (currentMap, marker) ->
return () ->
for polyline in Gmaps.map.polylines
polyline.serviceObject.setOptions({strokeOpacity: 0.1}

Related

How to use FSharpPlus.Lens to specify the index of a list?

The sample code of the documentation defines _pageNumber using List._item, but I can't seem to find an example of its use.
I tried the following code but it gave an error.
view (Book._pageNumber 1) rayuela // error
How would it be used?
I'm seeing the same thing:
No overloads match for method 'Zero'".
The problem is caused by the _Some lens, which doesn't work with record types, because they don't have a default (i.e. "zero") value:
let inline _pageNumberOpt i b =
_pages << List._item i <| b
let pageOpt = view (_pageNumberOpt 1) rayuela // this is fine
let page = view _Some pageOpt // this doesn't work, because the input is an Option<Page>
let x = view _Some (Some 1) // this works, because the input is an Option<int>
This appears to be a limitation in FSharpPlus that wasn't accounted for in the documentation. If you want to work around the problem, you can define Page.Zero yourself, and then the example will compile:
type Page =
{ Contents: string }
static member Zero = { Contents = "" }
let page = view (Book._pageNumber 1) rayuela
printfn $"{page}" // output is: { Contents = "The End" }
let noPage = view (Book._pageNumber 5) rayuela
printfn $"{noPage}" // output is: { Contents = "" }
Page.Zero will only be called if you ask for a page that doesn't exist, but it needs to be there for the compiler in any case.
(FWIW, in my experience, FSharpPlus is a very, very delicate beast. It's an interesting experiment, but it breaks easily. And when it breaks, the compiler errors are mind-boggling.)
Brian's answer is very accurate from the technical viewpoint but conceptually misses the most important point: you're "viewing" a partial lens (also called prism), instead of "previewing" it. This is not a limitation of F#+, this is just how lens behaves.
Some background: Prisms or partial lenses are like a lens that can fail, so in principle you can't use the view operation on them because it's an operation that always succeed, or better said doesn't consider a failure, you should use the preview operation which returns an option.
The composition rules state that the result of composing:
a lens with a lens is a lens
a lens with a prism (or the other way around) is a prism
a prism with a prism is a prism
This is, as soon as there is a prism in the composition chain the result will be a prism.
In our case we have _pages << List._item i << _Some which are lens composed with lens composed with _Some which is a prism, so _pageNumber i will be a prism.
Now, what happens if you use view for a prism? The zero value represents a failure, for instance the zero value of an option is None, but here there is no zero value specified.
Brian is right in that the error message is misleading, a better error would be "don't use view over a prism", but instead what happen is to try to get a naked value (not inside an option) which can represent failures with zero.
TL; DR
use instead:
preview (Book._pageNumber 1) rayuela // Some { Contents = "The End" }
Someone should send a PR to add that line to the docs.

Migrating to Places 4.0 SDK, how to migrate place Bias?

I am migrating to the new places SDK 4.0
The old func was:
findAutocompletePredictions(fromQuery: query,
bounds: bounds,
boundsMode: .bias,
filter: filter,
sessionToken: token) { (prediction, error) in
callback(prediction, error)
}
the new func as per docs is
findAutocompletePredictions(fromQuery: query,
filter: filter,
sessionToken: token) { (prediction, error) in
callback(prediction, error)
}
I see that bounds bias is now set on the GMSAutocompleteFilter filter
This has a locationBias property where i set some and it takes a parameter of <GMSPlaceLocationBias>
The issue i have is there is no info on what to provide here...GMSPlaceLocationBias is a protocol, and i have no idea what im meant to use object wise to provide the old bounds data.
Conforming to the protocol gives me a locationBiasURLQueryItem fun to populate, with no further documentation on what should go in this function
So im stuck and cant upgrade as there doesnt seem to be a clear way forward.
Anyone have any ideas? Docs are here: https://developers.google.com/places/ios-sdk/reference/interface_g_m_s_places_client#ab60773feec0e68751c5a7f1066b9d252)
My attempt to construct the filter is:
let filter = GMSAutocompleteFilter()
if case .location(let location) = _locationController.locationStatus {
filter.locationBias = .some(location)
}
But obviously my custom location model object doesnt confirm to GMSPlaceLocationBias and is a struct so cant be used and errors
I got totally lost on this as well, but just found an example buried in one of the guides here.
In short the implementation looks like this:
let filter = GMSAutocompleteFilter()
filter.locationBias = GMSPlaceRectangularLocationOption(bounds.northEast, bounds.southWest)
Here I'm using the same bounds I had previously been using in 3.x (in my case from the map currently being displayed) to get those northEast and southWest coordinates, but you can generate your own based on how where you are trying to bias results.
I wish they had just made ANY indication in their docs that this was the intended way to do it.

Possible to make a composite symbol?

When editing a vertex I would like to substitute the vertex symbol with SimpleMarkerSymbol and a TextSymbol but that appears to be impossible. Any suggestions on how I could do this? I want the appearance of dragging something like this (text + circle):
After taking some time to look at the API I've come to the conclusion it is impossible. Here is my workaround:
editor.on("vertex-move", args => {
let map = this.options.map;
let g = <Graphic>args.vertexinfo.graphic;
let startPoint = <Point>g.geometry;
let tx = args.transform;
let endPoint = map.toMap(map.toScreen(startPoint).offset(tx.dx, tx.dy));
// draw a 'cursor' as a hack to render text over the active vertex
if (!cursor) {
cursor = new Graphic(endPoint, new TextSymbol({text: "foo"}));
this.layer.add(cursor);
} else {
cursor.setGeometry(endPoint);
cursor.draw();
}
})
You could use a TextSymbol to create a point with font type having numbers inside the circle. Here is one place where you can find such font. http://www.fontspace.com/the-fontsite/combinumerals
Wont be exactly as shown in the image but close enough. Also some limitation it wont work with IE9 or lower (this is as per esri documentation, as I am using halo to get the white border).
Here is the working Jsbin : http://jsbin.com/hayirebiga/edit?html,output use point of multipoint
PS: I have converted the ttf to otf and then added the font as base64, which is optional. I did it as I could not add the ttf or otf to jsbin.
Well, Achieve this seems impossible so far however ArcGIS JS API provides a new Application/platform where you can generate single symbol online for your applications.
We can simply create all kind of symbols(Provide by ESRI) online and it gives you on the fly code which you just need to paste in your application.
This will help us to try different type of suitable symbols for the applications.
Application URL: https://developers.arcgis.com/javascript/3/samples/playground/index.html
Hoping this will help you :)

Deedle - create empty list and series

I am new to F#, looking at it as an alternative to Matlab.
In reference to this question, how can I create an empty Serie and an empty Frame.
If I did not just miss it, why an empty Serie or Frame has not been designed in the library,
something like list.empty ?
Adding Frame.empty and Series.empty is a great suggestion. I think these should be in the library and I'm adding an issue to GitHub to make sure they get added.
In the meantime, you should be able to use something like this:
let empty : Series<int, float> = series []
let empty : Frame<int, string> = frame []
Note that I had to add type annotations - from my code snippet, the compiler cannot figure out what is the type of keys and values, so I had to explicitly specify that (but if you use the values as arguments to other functions, then this should not be needed).
The second line does not actually work in the current version, because of a bug (oops!) so you can use Frame.ofRows instead, which works fine:
let frame : Frame<int, string> = Frame.ofRows []
EDIT: The bug is now fixed in version 0.9.11-beta

Pass null values to SVG path (using d3.js) to suppress missing data

Using jQuery Flot, I can pass a null value to the plotting mechanism so it just won't draw anything on the plot. See how the missing records are suppressed:
I'm looking to move to d3js, so that I can have deeper low level control of the graphics using SVG. However, I have yet to find out how to do that same process of suppressing missing records. The image below is an attempt to do this, using a value of 0 instead of null (where the d3 package breaks down). Here is some code to give you an idea of how I produced the graph below:
var line = d3.svg.line()
.x(function(d) {
var date = new Date(d[0]);
return x(date);
})
.y(function(d) {
var height = d[1];
if (no_record_exists) {
return y(0);
}
return y(height) + 0.5;
});
I looked up the SVG path element at the Mozilla Developer Network, and I found out that there is a MoveTo command, M x y, that only moves the "pen" to some point without drawing anything. Has this been implemented in the d3js package, so that I won't have to create several path elements every time I encounter a missing record?
The defined function of d3.svg.line() is the way to do this
Let's say we want to include a break in the chart if y is null:
line.defined(function(d) { return d.y!=null; })
Use line.defined or area.defined, and see the Area with Missing Data example.

Resources