Google Maps with Meteor and a reactive InfoWindow - google-maps

I have a google maps API v3 application for meteor that I'm currently working on. When a person clicks on a marker, it shows an infoWindow with some at-window-creation time static content.
What I would like to do is use a reactive template to render the infoWindow's contents, either directly as HTML which can change or by referring to a dom element that updates reactively.
I've verified that if I use an infoWindow to refer to a DOM element, and that element's contents change, the Maps API updates the on-screen window properly. However, I am having problems with two issues:
(1) Closing the window destroys the DOM element, so it would have to be re-created. This is possibly easy enough to handle with a "if it exists update it, else create it, insert it, and update it" process.
(2) UI.render doesn't appear to be dynamic, so creating it, inserting it, and updating it is harder than it feels like it should be.
I am still an intermediate Meteor hacker, so forgive me if I'm making this too hard on myself.

For #1, make a clone: content: $('.stats').clone()[0]
For #2, you'll need to create a dependency. The docs do a pretty good job of explaining it & without knowing your reactive data source catalyst I can't help too much more (I assume it's a Session var in the example). Oh, and if it's based on new entries from a collection, check out the .observe() function.
Template.name.created = function() {
Session.set('stats',10);
statsDep = new Deps.Dependency();
};
statsDep.depend();
var dropWindow = new google.maps.InfoWindow({
content: $('.stats').clone()[0]
});
statsDep.changed();

Related

how to change a CesiumJS viewer's baselayer url

i am using a CesiumJS instance to display a base map of the earth using a imageryProvider from source A.
var viewer = new Cesium.Viewer('cesiumContainer', imageryProvider:providerA);
Now while using the Viewer I would like to be able to change this map to get images from providerB at a certain event.
I tried:
viewer.scene.imageryLayers.get(0).imageryProvider.url = providerB.url
However that does not seem to work and also feels quite like hack anyway.
I could not find anything in Cesium's documentation .
Is this at all possible without restarting / recreating the viewer instance?
I know that there is a Cesium.BaseLayerPicker (https://cesium.com/docs/cesiumjs-ref-doc/BaseLayerPicker.html)
However I do not see what method this picker calls on "select" )
Thanks a lot.
The BaseLayerPicker widget calls this code when the user selects a new layer.
There's a lot of boilerplate widget management in that block of code, but for your sake, only a couple of the lines are critical. First, the old existing active imagery layer is searched for, and removed:
imageryLayers.remove(layer);
Then, a new imagery provider is constructed and added at index 0, the first position, which is the base imagery layer:
imageryLayers.addImageryProvider(newProviders, 0);
You can directly change the URL of the provider but you should also change appropriate parameters("layers" in case of WMS, "layer", "style", "format", "tileMatrixSetID " ... in case of WMTS) depending on the type of provider(WMS or WMTS).

How to load two forge viewers in single web page

I am trying to add two forge viewers in a single web page. I am using "react-forge-viewer" npm package to do that, but for some reason, only one viewer gets loaded and another one stays at "starting viewer..." state. It would be really great if anyone could help me resolve this problem.
I think this might be because of the dependency on class names or ID's.
Also, I want to synch their events in such a way that if I change camera view by dragging on on viewer same thing should reflect on another viewer as well.
You can easily fit multiple Viewers together, just be sure to initialize them separately with distinct container divs:
var viewer1 = new Autodesk.Viewing.Private.GuiViewer3D(document.getElementById('MyViewerDiv1'));
var viewer2 = new Autodesk.Viewing.Private.GuiViewer3D(document.getElementById('MyViewerDiv2'));
Autodesk.Viewing.Initializer(options1, function() {
viewer1.start();
viewer1.load(...);
});
Autodesk.Viewing.Initializer(options2, function() {
viewer2.start();
viewer2.load(...);
});
And you can sync the states of two viewers by subscribing to the CAMERA_CHANGE_EVENT, but beware pitfalls like endless loops - you can overcome this by implementing critical blocks to ensure only one viewer is exclusively requesting the other viewer to sync at any given time:
viewer1.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, function()
{
//critical block to prevent endless chained loop of events
viewer2.restoreState(viewer1.getState())
});
viewer2.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, function()
{
//critical block to prevent endless chained loop of events
viewer1.restoreState(viewer2.getState())
});
See a working sample here.
P.S:react-forge-viewer is a third party package not authored by Autodesk as is noted in its own README so you might need to contact its author if you have issues with it.

Retrieving all address information along Google Maps route

I am developing an Windows Forms application using VB.NET that offers the user to lookup addresses on Google Maps through a Web Browser. I can also successfully show the directions between two points to the user, as well as allow the user to drag the route as he/she pleases. My question now is - is it possible for me to get the lattitude/longitude information of the route, i.e. the overview_polyline array of encoded lattitude/longitude points and save it to e.g. a text file on my computer? Or is it possible to get a list of all the addresses located both sides of the route over the entire length of the route, and then save the data to a file on my computer? I'm using HTML files to access and display the Google Maps data in the Web Browser item.
Thank you
This is actually pretty simple if your just looking for the screen coordinates.
// this probably should be in your form initialization
this.MouseClick += new MouseEventHandler(MouseClickEvent);
void MouseClickEvent(object sender, MouseEventArgs e)
{
// do whatever you need with e.Location
}
if your strictly looking for the point in the browser, you need to consider the functions
browser.PointToClient();
browser.PointToScreen();
So, this method is usable if you know exactly where your form is (easy to get its coords) and where you webbrowser control is (easy to get coords of this as well since it's just a control in your form) and then, as long as you know how many pixels from the left or right, and from the top or bottom the image will be displayed, once you get the global mouse click coords (which is easy) you can predict where it was clicked on the image.
Alternatively, there are some scarier or uglier ways to do it here...
You can use the ObjectForScripting property to embed code to do this in the webbrowser. It's ugly to say the least. MSDN has some documentation on the process here: http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.objectforscripting.aspx
Because its really ugly, maybe a better solution is to use AxWebBrowser - it's ugly too but not so scary.
In addition, I found this post of someone wanting to do it on a pdf document, and a MSFT person saying its not possible, but really what he is trying to say is that it isn't built in, even with a pdf document its still possible to predict with high to certain accuracy where it was clicked if you use the first method i described. Here is the post anyway: http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/2c41b74a-d140-4533-9009-9fcb382dcb60
However, it is possible, and there are a few ways to do it, so don't get scared from that last link I gave ya.
Also, this post may help if you want to do it in javascript:
http://www.devx.com/tips/Tip/29285
Basically, you can add an attribute on the image through methods available in the webbrowser control, you can add something like onclick="GetCoords();" so when it is clicked, the JavaScript function will get the coords, and then you can use javascript to place the values in a hidden input field (input type="hidden") which you can add through the webbrowser control, or if there is one already on the page, you can use that. So, once you place the coords using javacript into that input field, you can easily grab the value in that using the webbrowser control, eg:
webbrowser1.document.getElementById("myHiddenInputField").value
That will get the value in that field, which you've set through JavaScript. Also, the "GetCoords()" function i mentioned is called SetValues() in the javascript method link i provided above (in the devx.com site) but I named it GetCoords because it makes more sense and didn't want to confuse you with the actual name they used, you can change this to any name you want of course. Here is the javascript they were using, this only gets the coords into a variable, doesn't put it into a hidden input field, we will need to do that in addition (at the end of the javascript SetValues/GetCoords function).
function SetValues()
{
var s = 'X=' + window.event.clientX + ' Y=' + window.event.clientY ;
document.getElementById('divCoord').innerText = s;
}
These guys are just saving it inside a div element, which is visible to users, but you can make the div invisible if you want to use a div field, there is no advantage or disadvantage in doing that, you would just need to set the visible property to false using javascript or css, but still, it is easier to use a hidden input field so you don't need to mess with any of that.
Let me know how you get along.

Html5 drag and drop unicode chessboard

I am trying to do html5 dragndrop on my html5/css chessboard using unicode pieces but have a problem at the moment with it.
On dragging & dropping the whole 'li' element seems to move & on drop this disrupts the board.
This can be seen on the chess WordPress site at:
http://www.buryknightschess.org.uk/play-chess/
(As can be seen I asked for help with this on SitePoint Forums but haven't had a reply to help yet from there).
Possibly I somehow need just to make the unicode chess pieces draggable & not the whole chess square (<li></li>).
I shall keep trying to fix this but meanwhile I would greatly appreciate any advice to help with this html5 dragndrop issue. I look forward to helpful replies, many thanks
The reason the <li/> is being moved (thus rearranging the chess board) is because in your drop function is calling appendChild:
function drop(event) {
var element = event.dataTransfer.getData("Text");
// This changes the DOM
event.target.appendChild(document.getElementById(element));
event.stopPropagation();
return false;
}
Instead of moving that actual DOM node, the drop function should copy the innerHTML of the node that's being dragged. Here's how the new drop would look function:
function drop(event) {
var coordinate = event.dataTransfer.getData("Text");
var element = document.getElementById(coordinate);
event.target.innerHTML = element.innerHTML; // Moving piece to new cell
element.innerHTML = ""; // Clearing old cell
event.stopPropagation(); // Consider using `event.preventDefault` instead
return false;
}
Also, I'd consider using event.preventDfault instead of event.stopPropagation. This makes it possible to add new drop listeners to the board or one of its parents. For example you may want to add a drop listener to the document body to handle the case where a user tries to drag a piece off the board.
As general remark, have you considering using jQueryUI draggable and droppable libraries? You'd be able to support much richer drag/drop interactions such as snap-to-grid movement and delayed starts. Also, HTML5 drag-and-drop is typically used to allow users to drag files from their OS desktop onto the a web page. The way your using it is totally fine, it's just a little strange.

Window settings for Google Maps widget

I've got a plain-vanilla google maps widget sitting in a page and I'd like it if the driving directions opened up in a new window instead of taking over the current window. Is there a setting for this?
The driving directions go into whatever HTML element you specify as the second argument when you construct the GDirections object. So I guess that means you'd have to create the window before you create the GDirections object, which is likely not what you want.
The other thing that jumps out, looking at the documentation, is that you can call the load() method with the option getSteps = true. It's not clear what the "steps" data looks like, but I assume it essentially comes back as an HTML string. (Actually, it's not even clear how you get the data in the first place, but I assume it's GDirections.getSteps() or something similar.) So then when the "load" event happens, you can create the new window then put the "steps" data in it.