How do you implement Google Maps in Uno WASM - google-maps

I'm new to Uno Platform and I need help adding Google Maps to my app. Since MapControl doesn't provide WASM support, it seems like I need to embedd a javascript component. This should be possible according to https://platform.uno/blog/how-to-embed-javascript-components-in-c-built-uno-webassembly-web-applications/ . But I can't seem to make it work.
I have a javascript file containing the following, taken directly from the official google maps site. Also not sure where to put the map API key.
// Initialize and add the map
function initMap() {
// The location of Uluru
const uluru = { lat: -25.344, lng: 131.036 };
// The map, centered at Uluru
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 4,
center: uluru,
});
// The marker, positioned at Uluru
const marker = new google.maps.Marker({
position: uluru,
map: map,
});
}
I also have this class, tried doing it similar to part 3 in the official Uno Platform Embedd Javascript Components guide.
public class GoogleMapsController : FrameworkElement
{
public GoogleMapsController()
{
LoadJavaScript();
}
private async void LoadJavaScript()
{
await this.ExecuteJavascriptAsync("initMap()");
}
}
To display the map in the xaml page:
<local:GoogleMapsController x:Name="googlemaps" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" />
When I run the app the map doesn't show up. Does anyone know what I am doing wrong?
The following shows up in the web console
fail: Windows.UI.Core.CoreDispatcher[0]
dotnet.js:1 Dispatcher unhandled exception
dotnet.js:1 System.ApplicationException
dotnet.js:1 at TestMaps.GoogleMapsController.LoadJavaScript () <0x2f90540 + 0x000e6> in <filename unknown>:0
dotnet.js:1 at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) <0x2f9ba10 + 0x00010> in <filename unknown>:0
dotnet.js:1 at Windows.UI.Core.CoreDispatcherSynchronizationContext+<>c__DisplayClass3_0.<Post>b__0 () <0x2f9b9d0 + 0x00014> in <filename unknown>:0
dotnet.js:1 at Windows.UI.Core.CoreDispatcher.DispatchItems () <0x2a8a0a0 + 0x001e6> in <filename unknown>:0
If I change the LoadJavaScript() to synchronous in GoogleMapsController, the following shows up in the web console.
dotnet.js:1 Error #1 "ReferenceError: google is not defined" executing javascript: "
put_char # dotnet.js:1
dotnet.js:1 (function(element) {
put_char # dotnet.js:1
dotnet.js:1 initMap()
put_char # dotnet.js:1
dotnet.js:1 })(Uno.UI.WindowManager.current.getView(38002));
put_char # dotnet.js:1
dotnet.js:1 "

Got it working, I will probably write a blogpost on it later.
Get Google Maps API key
You can follow any tutorial available on the web on how to get an API key via the Google Developer Console. It involves creating a project, adding required billing information, creating API key and then enabling Google Maps API for it. Make sure to restrict the API key when you plan to go public so that someone does not misuse your key for their purposes and use up your billing this way.
Add a custom index.html to your WASM project
Because Google Maps requires loading an external JavaScript library, it is useful to load it ahead of time when your app first loads. to do that, add a index.html file to the root of your WASM project with the following content:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<script type="text/javascript" src="./require.js"></script>
<script type="text/javascript" src="./mono-config.js"></script>
<script type="text/javascript" src="./uno-config.js"></script>
<script type="text/javascript" src="./uno-bootstrap.js"></script>
<script async type="text/javascript" src="./dotnet.js"></script>
<!-- Google Maps libs here: -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=MYAPIKEY&libraries=&v=weekly"></script>
$(ADDITIONAL_CSS)
$(ADDITIONAL_HEAD)
</head>
<body>
<div id="uno-body" class="container-fluid uno-body">
<div class="uno-loader"
loading-position="bottom"
loading-alert="none">
<!-- Logo: change src to customize the logo -->
<img class="logo"
src=""
title="Uno is loading your application" />
<progress></progress>
<span class="alert"></span>
</div>
</div>
<noscript>
<p>This application requires Javascript and WebAssembly to be enabled.</p>
</noscript>
</body>
</html>
Note that most of the code is boilerplate that is the default in Uno WASM projects (see here). Replace MYAPIKEY with your API key from developer console.
Now you need to instruct the WASM bootstrapper to use this custom index.html. Double-click the .csproj in the Solution Explorer and add the following:
<PropertyGroup>
<WasmShellIndexHtmlPath>index.html</WasmShellIndexHtmlPath>
</PropertyGroup>
Create custom Maps element
Similarly to the tutorial in docs, I created the following element:
#if __WASM__
using System;
using Uno.UI.Runtime.WebAssembly;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
namespace UnoWasmGoogleMaps
{
[HtmlElement("div")]
public class GoogleMapView : FrameworkElement
{
private readonly string _mapObjectName = "map_" + Guid.NewGuid().ToString().Replace("-", "");
public GoogleMapView()
{
Background = new SolidColorBrush(Colors.Transparent);
LoadMap();
}
private void LoadMap()
{
var javascript = $#"var {_mapObjectName} = new google.maps.Map(element, {{ center: {{lat: -34.397, lng: 150.644}}, zoom: 8 }});";
this.ExecuteJavascript(javascript);
}
}
}
#endif
Note I am using a custom unique variable name to store the map object created by Google Maps API. You can use this variable name to manipulate the map and call some functions on it.
Use the element
Finally, you can use the element in your app like this:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<local:GoogleMapView />
</Grid>
Result

Related

Google Map issue with XHTML file

I am facing a weird issue with Google Map API V3. I had a previous version of the code, which I migrated to new version V3. The extension is XHTML since this particular file is used as a control in other application. I have created a sample code, which when I execute as stand alone runs fine and displays the google map, but when the similar file is called through another application it is causing an issue where map is loaded but is invisible. Just for information i am using this file from Informatica IDD application. Below is a snippet. Looking for any kind of lead.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="https://maps.googleapis.com/maps/api/js?&3.21&key=AIzaSyBO11CFgFCL8GnV3-tWZyQOmA8mbO9MP8E&sensor=false"
type="text/javascript"></script>
<script type="text/javascript">
/* CONSTANTS */
var geocoder = null;
var map = null;
/* INITIALIZATION */
function initialize() {
alert("initialize");
geocoder = new google.maps.Geocoder();
// Draw the map
/*var startPoint = parseCoordinate(VALUE_SITE_COORDINATE);
alert(startPoint);*/
var startPoint = new google.maps.LatLng(24.886, -70.268);
var mapProp = {
center:startPoint,
zoom:5,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
map =new google.maps.Map(document.getElementById("map_canvas"),mapProp);
alert("after new map");
google.maps.event.addListenerOnce(map, 'idle', function() {
google.maps.event.trigger(map, 'resize');
alert("in idle");
});
var bimage = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
// Set up our GMarkerOptions object
//markerOptions = { icon:blueIcon };
var marker = new google.maps.Marker({
position: startPoint,
map: map,
icon: bimage
});
marker.setVisible(true); // visible_changed triggered
marker.setMap(map);
}
//google.maps.event.addDomListener(window, 'load', initialize);
google.setOnLoadCallback(initialize);
</script>
</head>
<body>
<div id="map_canvas" style="width:850px;height:850px;">
<!--<div>
<h:form id="geomap">
<div class="title-bar">
<h:outputText value="Geo Fence Maintenance"/>
</div>
<div style="width:50%;float:left;">
</div>
<div style="width:50%;">
</div>
<div style="width:50%;float:left;">
</div>
<div style="width:50%;">
</div>
<div style="width:100%;padding-bottom:10px;">
<div style="float:left;">
</div>
</div>
<div>
<div id="divCoordinates" style="width:200px;height:200px;float:left;padding-top:5px;padding-left:5px;">
</div>
<div>
<div id="map_canvas" style="width:400px;height:400px;"></div>
</div>
</div>
</h:form>
</div>-->
</div>
</body>
</html>
Further Analysis
I think i found the root cause but not the solution. The issue is my google map is being called through JSF. I guess some update in IE11 is breaking the functionality. The similiar problem i have encountered in link below. http://www.mashups4jsf.com/gmaps4jsf-examples2-3.0.0/pages/mapAjax.xhtml It have google map invisible in IE 11 but shows up when it is opened in firefox. I have similiar kind of issue with IE11. Any suggestion how to fix it?
You have "amp;" in your script src url, but I think that is probably as result of your copy/pasting. Definitely check your src url to make sure you are actually loading the google maps api.
My guess is that your real problem is this line:
google.setOnLoadCallback(initialize);
You are not loading the Google API so google.setOnLoadCallack() does not exist when you are calling it.
Add this to your page just before the script tag for the google maps:
<script src="https://www.google.com/jsapi"></script>
You will need to add your API key if you want it to work for your application when it is deployed to your server.
Alternatively, you could put a callback function in the url for the google maps script:
<script src="https://maps.googleapis.com/maps/api/js?callback=initialize" async defer></script>

Google Map won't pull marker symbol from Dropbox

I'm doing a google map with custom symbols on locations provided by the client. Pasted below is a simplified version. When I set the path to the marker graphic .png in my own hard drive, and view the map in my own browser, everything works fine: The custom markers appear in the correct locations.
However, when I set the path to the marker .png in Dropbox, the marker does not appear on the map- neither with nor without the "?dl=0" suffix that Dropbox adds to the filename. I've also tried keeping the graphic on my Google Drive and pulling it from there; That didn't work either.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>GoogleMapHawthorne It Works!</title>
<script src="http://maps.google.com/maps/api/js?sensor=false"
type="text/javascript"></script>
</head>
<body>
<div id="map" style="width: 950px; height: 525px;"></div>
<script type="text/javascript">
// locationsSC = locations in Service, Community Asset layer
var locationsSC = [
['Fish Emergency Services', 45.512388, -122.651950],
['Southeast Community Bike Fix-it Station', 45.512360, -122.634061],
['Southeast Kitchen Share', 45.508305, -122.637014],
['Southeast Tool Library', 45.508312, -122.637690],
['Southeast Uplift Neighborhood Coalition', 45.513445, -122.627480]
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: new google.maps.LatLng(45.510000, -122.630930),
mapTypeId: google.maps.MapTypeId.ROADMAP,
});
// adding Service, Community Asset markers
var markerSC, sc;
for (sc = 0; sc < locationsSC.length; sc++) {
markerSC = new google.maps.Marker({
position: new google.maps.LatLng(locationsSC[sc][1], locationsSC[sc][2]),
map: map,
icon: {
url: 'https://www.dropbox.com/s/set461kj7rt1zv5/ServiceBrownCog.png',
scaledSize: new google.maps.Size(25, 25)
}
});
google.maps.event.addListener(markerSC, 'click', (function(markerSC, sc) {
return function() {
infowindow.setContent(locationsSC[sc][0]);
infowindow.open(map, markerSC);
}
})(markerSC, sc));
}
</script>
</body>
</html>
Is the problem in my code? Or is it Dropbox?
I'm just beginning to learn JavaAcript; Most of the code is snippets copied (by typing) from various tutorials.
I have no qualms about pasting the actual file path in the code here. That file location is going to be public anyway. If anyone can think of a good reason I shouldn't do this, feel free to say so- and why.
Above all, thanks in advance.
https://www.dropbox.com/s/set461kj7rt1zv5/ServiceBrownCog.png isn't a link to an image. It's a link to a web page that (among other things) shows you the image.
To get a link to the image itself, try https://www.dropbox.com/s/set461kj7rt1zv5/ServiceBrownCog.png?raw=1. For more details, see https://www.dropbox.com/help/201.

google sign in not returning error also not signing in

I am trying to make google sign in work on my intranet site which currently uses integrated windows authentication - I want to get away from that because I need to support ChromeBooks and pretty much everything here is going google......
This is what IS working:
I get a sign in button. I can see in the console log that it is using my google developer client id:
XHR finished loading: GET "https://accounts.google.com/o/oauth2/iframerpc?action=checkOrigin&origin=ht…d=777682448638-5tpyaddayaddyadddarvnbr3p6.apps.googleusercontent.com".
If I click the button on a machine where I am not logged into google I will geta prompt to log into google.
If I click the button on a machine where I am logged into google but have not visited this site before then I will get the authorization request for my email and profile to be shared with my web application.
If I have done the above, and click the button then there is a flash of a pop-up window that goes away immediately.
What is NOT working:
My website never gets any onSuccess back....... so the button ALWAYS says "Sign in with Google" I don't get to the next step of "Signed in as molly ......"
Here is a shortended version of my code - please note that right now my website uses the integrated windows authentication - that is what I am trying to port away from so we can use ChromeBooks and other computers that are not using our windows login.
this is from my _Layout.cshtml page
#{
var username = WebSecurity.CurrentUserName;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Rutland City Public Schools - ACADEMIC SITE</title>
<link href="~/Styles/Styles.css" rel="stylesheet" type="text/css"/>
<link href="~/Styles/PrintStyles.css" rel="stylesheet" type="text/css" media="print"/>
<meta http-Equiv="Cache-Control" Content="no-cache">
<meta http-Equiv="Pragma" Content="no-cache">
<meta http-Equiv="Expires" Content="0">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
#RenderSection("script", required: false)
<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id" content="777682448638-5tpyaddayaddayaddavnbr3p6.apps.googleusercontent.com">
</head>
<body>
<div id="topRight">
Hello: #username <br> <br>
<div id="my-signin2" align="center" ></div>
<script>
function onSuccess(googleUser) {
console.log('Logged in as: ' + googleUser.getBasicProfile().getName());
}
function onFailure(error) {
console.log(error);
}
function renderButton() {
gapi.signin2.render('my-signin2', {
'scope': 'https://www.googleapis.com/auth/plus.login',
'width': 150,
'height': 30,
'longtitle': true,
'theme': 'light',
'onsuccess': onSuccess,
'onfailure': 'oops!'
});
}
</script>
<script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
ignore google button!
</div>
<div id="mainContent">
#RenderBody()
</div>
</body>
</html>
If I open up "Inspect Element" when I am in chrome I can see that under the network tab it clearly goes off and does some gets to google. In the console tab I only see the XHR finished loading: GET "https://accounts.google................." message.
What is going on here? Why am I not getting the onSuccess?
Thank you!!!!
Added more notes:
I added a link:
Sign in
that calls this function:
function signIn() {
var auth2 = gapi.auth2.getAuthInstance();
console.log(auth2);
From the console results I can see my website, and my client id, but again I see nothing about my actual user.
jF {zd: Object, po: "single_host_origin", zt: true, ha: true, G: undefined…}
B: bY
B: "777682448638-5tp3rss17g1qarc3em0opcr4rvnbr3p6.apps.googleusercontent.com"
Db: "http://rcps"
Ei: undefined
El: undefined
G: "google"
Ka: false
Ld: Object
openid.realm: undefined
redirect_uri: "http://rcps/academic/academic"
response_type: "token id_token"
scope: "openid profile email"
With the Google Sign-In (gapi.auth2) JavaScript client libraries, you should probably be using listeners to check the state of the client. I'm not sure exactly how you're rendering the button but you might want to take a good look at the Google Sign-in quickstart.
Although I have found using listeners to have advantages over using the success callback, the following code works for me (I see onWin upon sign-in with the z variable containing the authorization response):
function onFail(z){ alert('Fail' + JSON.stringify(z)); }
function onWin(z){ alert('Win' + JSON.stringify(z)); }
gapi.load('auth2', function() {
gapi.signin2.render('signin-button', {
scope: 'https://www.googleapis.com/auth/plus.login',
onsuccess: onWin,
onfail: onFail,
fetch_basic_profile: false });
gapi.auth2.init({fetch_basic_profile: false,
scope:'https://www.googleapis.com/auth/plus.login'}).then(
function (){
console.log('init');
auth2 = gapi.auth2.getAuthInstance();
auth2.isSignedIn.listen(updateSignIn);
auth2.then(updateSignIn());
});
});
Do things when sign-in changes (e.g. show/hide authorized UI):
var updateSignIn = function() {
console.log('update sign in state' + auth2.isSignedIn.get());
}
At any point when auth2.isSignedIn.get() returns true, you can use auth2.currentUser.get() to retrieve the profile data for the currently signed in user.
I had similar problems when testing on localhost. When I pushed my code onto my production server the simple example provided by Google worked perfectly as advertised. The button's values changes or stays accordingly even after a page refresh.
Perhaps your browser is configured to block third party cookies. If so, disable that feature. You may also want to have a note on your login page mentioning that third party cookies are required so that your users will know to do the same.

Google Maps fails to load with angularjs

Hi i've been attempting to load Googlemaps onto the page when the user clicks on the link. I've been attempting to follow Using google maps with angularjs and angular ui but the map doesn't appear. On localhost, the error i get is: no module:map testing. What does no module here imply? I keep running into such errors. It works on JSfiddle for some reason...The working example.
Html file:
<div ng-app='maptesting'>
<div ng-controller="MapCtrl">
<div id="map_canvas" ui-map="myMap"
style="height:300px;width:400px;border:2px solid #777777;margin:3px; border:1px solid"
ui-options="mapOptions"
ui-event="{'map-idle' : 'onMapIdle()'}"
>
</div>
<!--In addition to creating the markers on the map, div elements with existing google.maps.Marker object should be created to hook up with events -->
<div ng-repeat="marker in myMarkers" ui-map-marker="myMarkers[$index]"
ui-event="{'map-click': 'markerClicked(marker)'}">
</div>
</div>
</div>
The javascript file:
//Add the requried module 'angular-ui' as a dependency
angular.module('maptesting', ['ui.map','ui.event']);
function MapCtrl($scope) {
var ll = new google.maps.LatLng(13.0810, 80.2740);
$scope.mapOptions = {
center: ll,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//Markers should be added after map is loaded
$scope.onMapIdle = function() {
if ($scope.myMarkers === undefined){
var marker = new google.maps.Marker({
map: $scope.myMap,
position: ll
});
$scope.myMarkers = [marker, ];
}
};
$scope.markerClicked = function(m) {
window.alert("clicked");
};
}
Live example:
On plunker: here
On JSfiddle: here.
On another note, would it be better to code the google maps and angularjs integration using angularui, from scratch or using google maps with angular? The anuglarui one looks great but when i tried it it didn't work too. I read in a google circle that it wasn't updated for a while which could be why it isn't working well.
Answer:
Yep all I was missing were the script tags. Namely:
<script src="http://www.flocations.com/static/vendor/angular-ui/event/event.js"></script>
<script src="http://www.flocations.com/static/vendor/angular-ui/map/ui-map.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
Your Plunk doesn't have <script></script> elements for ui.map or ui.event. For example, you might want to include these in your <head>:
<script src="ui-event.js"></script>
<script src="ui-map.js"></script>

Is there a good way to integrate a google map to the apache openmeetings 2.0?

Is there a good way to integrate a google map to the apache openmeetings 2.0?
I search it and find use about openlaszlo http://code.google.com/p/openlaszloincubator/source/browse/trunk/googlemapsonlaszlo/?r=32#googlemapsonlaszlo%253Fstate%253Dclosed
and the site http://code.google.com/p/openmeetings/source/browse/trunk/singlewebapp/WebContent/lps/components/incubator/googlemap.lzx?r=3529 which don't base on openmeetings 2.0!
Does any one realize it?
Google has deprecated the Google Maps Flash APIs in late 2011.
"Consequently we have decided to deprecate the Maps API for Flash in
order to focus our attention on the JavaScript Maps API v3 going
forward. This means that although Maps API for Flash applications will
continue to function in accordance with the deprecation policy given
in the Maps API Terms of Service, no new features will be developed,
and only critical bugs, regressions, and security issues will be
fixed. We will continue to provide support to existing Google Maps API
Premier customers using the Maps API for Flash, but will wind down
Developer Relations involvement in the Maps API for Flash forum."
Therefore - if you are not already an existing Google Maps API Premier customer - you will not be able to utilize the Google Maps OpenLaszlo component in the incubator. You should instead use the Google JavaScript Maps API v3. The map object can be integrated using the <html /> tag in the SWF runtime. If you only plan to use the DHTML runtime you could attach the map object directly to the display object of a view.
Since the current version of OpenMeetings still seems to use the SWF runtime as the default target runtime, that leaves you with the option of using an iFrame through the <html src="" /> tag.
Here is a simple example based on the code you had in your comment. The example uses two files: One LZX file, and one HTML file containing the Google Maps example. Here is the LZX code:
<canvas height="500">
<class name="showGISWindow"
extends="view"
width="464" height="440">
<method name="setLatLong" args="lat,lng">
this.maps.callJavascript('centerMap(' + lat + ', ' + lng + ')' );
</method>
<button text="Show New York"
align="center"
onclick="parent.setLatLong(40.69847032728747, -73.9514422416687)" />
<html name="maps" src="gmaps.html"
x="15" y="45"
width="${parent.width - 30}"
height="${parent.height - 45}" />
</class>
<showGISWindow id="gis" x="10" y="10" />
</canvas>
And the corresponding gmaps.html page content, which is loaded into the iFrame:
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Map Simple</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map_canvas {
margin: 0;
padding: 0;
height: 100%;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
var map;
function initialize() {
var mapOptions = {
zoom: 8,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
}
function centerMap(lat, lng) {
map.setCenter(new google.maps.LatLng(lat, lng));
map.setZoom(11);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>
When the button is clicked, the OpenLaszlo apps calls the function centerMap(lat, lng) in the HTML page, and will center the map to New York. Here's a screenshot of the application in the SWF10 runtime: