Google Maps Engine Layer refresh after insert - google-maps

I have a Google Maps where i've added and MapsEngineLayer (i also tried with DynamicMapsEngineLayer you can check the code for both here: https://developers.google.com/maps/documentation/javascript/mapsenginelayers). On the website - HTML and Javascript - i have an edit button where i change, via Google Maps Engine API, some attributes of some features or add new features (geometries) to the datasource of that layer. Those inserts are made via an ajax call to php (similar to https://developers.google.com/maps-engine/documentation/feature-create).
All the authentication is made as a Service Account so the token for the layer and API is the some for 3600 seconds.
After the Insert/Update nothing appears on the map but, if i open a new private window all the modifications are there.
Wich is the best way to force the refresh of the MapsEngineLayer entirely or only the tiles affected by that insertion?
I already tried, after the insert:
mapsEngineLayer.unbindAll();
mapsEngineLayer.setMap(null);
mapsEngineLayer = null;
I can use GeoJSON to re-read all the features but the datasourcs have a lot of featues.

Try this to force a reload of the layer without destroying the entire map:
layer.setMap(null);
delete layer;
layer = new google.maps.visualization.MapsEngineLayer({ layerId: ... });
layer.setMap(map);
This should also work for DynamicMapsEngineLayer.

Related

How to change data in data layer before sending to Google Analytics?

I tried to change some values in the data layer before it reach my Google analytics account.
I used a custom HTML tag to manipulate the data Layer. Say I wanted to multiply my room count variable by 3,
<script type="text/javascript">
(function() {
var var7 = ({{DL_roomcount}})
var7 = 3*var7
dataLayer.push({
'roomcount' : var7
});
})();
</script>
Apparently, even though it shows the new values in the data Layer in preview mode, the new values never reached the analytics account.
The trigger type I used was - custom event & event name was 'gtm.load'. In preview mode datalayer shows roomcount as 3 but in analytics account its still 1.
My GA-debug console also shows 1 instead of 3.
Any help regarding this would be highly appreciated.
Thank you
You should push an event into the dataLayer at the same time that you are pushing the new value for roomcount so that you can access that new value:
// your other code
dataLayer.push({
'event': 'update roomcount',
'roomcount': var7
})
You can now access the new roomcount value if you trigger your tag to fire on the update roomcount event.
You need to look at when it is that those values are read; let me give you an example.
You click on the page.
This causes a data layer push.
That push causes a google analytics to fire off an event.
You use your custom tag to edit the data layer variable.
In this situation, it's too late. You've already missed the point at which Google Analytics recieves the information.
I recommend either editing the data layer push, the data layer variable, or the tag that sends the information to Google Analytics. Adding in a 4th party just makes it more complicated.

Program-generated KML file validates, but doesn't work

I had a co-worker that normally worked with Google Maps and now I am creating my first map. I am using what they developed in the past and making the changes for what I need. They created a script that sets some of the map defaults, so that is why things might look slightly different.
var map = new Map();
map.loadMap();
var kml = new google.maps.KmlLayer({ url: 'http://api.mankatomn.gov/api/engineeringprojectskml', suppressInfoWindows: true });
kml.setMap(map.map);
The map loads. My KML file doesn't load. I don't get any errors in the console. When I replace the url with a different URL http://www.mankato-mn.gov/Maps/StreetConstruction/streetconstruction.ashx?id=122 it'll work just fine. My new feed does validate. Is there a issue with my web service?
Update: After a few days, I am still having the issue. So I am pretty sure this isn't a DNS issue anymore. I created a jsFiddle to see if it is my code or something else. I started with Google's sample code and changed the URL of the KML file to both my web service and to a static version of the generated file. Both are valid KML files. Neither work. If there was a syntax error, wouldn't the API report that?
You can get the status of a KML layer with
kml.getStatus();
which in this case return:
"INVALID_DOCUMENT"
Now, if I request your URL from the browser, I get
<Error>
<Message>An error has occurred.</Message>
</Error>
So it seems if there ever was a valid KML there, it isn't anymore. Assuming from your question I can oly guess it was above weight limit, or you weren't associating it with a valid instance of map.
For getStatus to return something useful, you must wait for Google Maps API to try and load the KML layer you declared. For example, you can add a listener on the status_changed event.
var kmloptions={
url: 'https://dl.dropboxusercontent.com/u/2732434/engineeringprojectskml.kml',
suppressInfoWindows: true
};
var newKml = new google.maps.KmlLayer(kmloptions);
newKml.setMap(map);
google.maps.event.addListenerOnce(newKml, 'status_changed', function () {
console.log('KML status is', newKml.getStatus());
});
in this case (note that I'm using the alternative URL you used in the jsFiddle), I still get INVALID DOCUMENT.
Update: it seems the problem was the encoding of the file (UTF-16 BE is meant to be binary). I converted it to utf-8 and reindented (it's in my public dropbox now)
You can check if the DNS is setup by:
Going to the url in your browser. Do this with cache emptied and history ereased (private mode is best). If it ends up at your server and the right file it is not a DNS problem.
Move the file to a location you're sure it is reachable without any DNS issues. e.g. http://www.mankato-mn.gov/Maps/StreetConstruction/engineeringprojectskml
If the problem persists make sure that your KML syntax and Javascript is 100% correct. Also check out https://developers.google.com/maps/documentation/javascript/examples/layer-kml if you're still having any issues.

How can I generate a file like this for Bing Heat Map data?

I am working on a fairly simple Heat Map application where the longitude and latitude of the points will be stored in a SQL Server database. I have been looking at an example that uses an array of objects as follows (eliminated a lot of data for brevity):
/* Sample data to demonstrate Bing Maps Heatmap */
/* http://alastair.wordpress.com */
var CrimeData = [
new Microsoft.Maps.Location(52.67280, 0.94392),
new Microsoft.Maps.Location(52.62423, 1.29493),
new Microsoft.Maps.Location(52.62187, 1.29080),
new Microsoft.Maps.Location(52.58962, 1.72228),
new Microsoft.Maps.Location(52.69915, 0.24332),
new Microsoft.Maps.Location(52.51161, 0.99350),
new Microsoft.Maps.Location(52.59573, 1.17067),
new Microsoft.Maps.Location(52.94351, 0.49153),
new Microsoft.Maps.Location(52.64585, 1.73145),
new Microsoft.Maps.Location(52.75424, 1.30079),
new Microsoft.Maps.Location(52.63566, 1.27176),
new Microsoft.Maps.Location(52.63882, 1.23121)
];
What I want to do is present the user with a list of some sort that displays all the data sets that exist in the database (they each have a name associated with them) and then allow the user to check all or only a select few. I will then need to generate an array like the above to create the heat map. Any ideas on a good approach to this?
What you trying to achieve is more related to a web developement rather than only related to Bing Maps.
To summarize, you have multiple ways to do this but it really depends on what you are capable to do and what you need in the interface.
What process/technology?
First, you need to determine what process you want to follow to display the data and it will set the technology that you will use. The questions that you need to ask yourself are:
Do you want to be able to change the data sets dynamically without refreshing the whole page?
If yes, it means that you will have to use asynchronous data loading through a dedicated web service in order to avoid loading all the information at the initial load of the page.
Do you have lots of data to load?
If so, it might comfort you with asynchronous loading to avoid loading all data.
If not loading every elements in multiple arrays might be the simplest solution.
Implementation
So now, you want to create a web service to load the data asynchronously, you can take a look at the following websites :
http://www.asp.net/get-started
http://www.stefanprodan.com/2011/04/async-operations-with-jquery-ajax-and-asp-net-mvc/
There might be interesting other website, you will be able to find them. If needed, add comment and I'm sure the community will help you.
If you want to generate the data directly in the script, it could be simple as you can compose the JavaScript directly in your dynamically created HTML page (in your ASP.Net markup code or whatever technology you're using).

How add WMS layers with gwt-openlayers?

I'm trying to add WMS layer from remote ArcGIS server to my GWT web app. I'm using gwt-openlayers library.
My code:
MapOptions defaultMapOptions = new MapOptions();
mapWidget = new MapWidget("100%", "100%", defaultMapOptions);
Map map = mapWidget.getMap();
//gNormal = new GoogleV3("Google Normal", gOptions);
//map.addLayer(gNormal);
WMSParams wmsParams = new WMSParams();
wmsParams.setFormat("image/png");
wmsParams.setLayers("1");
wmsParams.setStyles("");
WMSOptions wmsLayerParams = new WMSOptions();
wmsLayerParams.setUntiled();
wmsLayerParams.setProjection("EPSG:3857"); // is it correct setting for WMS layer?
// wmsLayerParams.setProjection("EPSG:102113");
// wmsLayerParams.setProjection("EPSG:4326");
wmsLayerParams.setTransitionEffect(TransitionEffect.RESIZE);
String wmsUrl = "sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer";
arcGis = new WMS("ArcGis", wmsUrl, wmsParams);
map.addLayer(arcGis);
map.setBaseLayer(arcGis);
LonLat lonLat = new LonLat(-84.1,36.4); //USA
lonLat.transform("EPSG:4326", map.getProjection());
//System.out.println("map projection "+map.getProjection());
map.setCenter(lonLat, 3);
add(mapWidget);
I read many articles and SO questions but I still can't solve the problem. My problem is rendering pink tiles on the map instead of normal image. I copied image url as many stackoverflow answers suggested and saw the following:
http://localhost:8084/sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?FORMAT=image%2Fpng&LAYERS=1&STYLES=&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG%3A4326&BBOX=-135,45,-90,90&WIDTH=256&HEIGHT=256
Without localhost:8084 prefix url works fine and shows me small piece of map.
Questions:
1) How get rid from localhost prefix in WMS url? In my code wmsUrl look like sampleserver1... so it's correct. It seems my application adds it's root path to remote url.
2) I read that WMS layers should have the following projection - "EPSG:3857". Is it true? As i mentioned above when I manually put in the browser correct url without "localhost" prefix I saw some image but I'm not sure it's correct. Probably image is shifted.
3) My final goal is adding 2 layers to the map - Google Map layer and WMS layer. Google Map uses "EPSG:900913" as default projection. Could somebody give common tips to place google layer and WMS layer in one map. May be there are some tricks, common mistakes related to projections an so on.
In the wmsUrl variable, you are missing the "http://", that may help.
Pink tiles generally mean that the data source was not found, so this is where you should look for the problem. Try checking the wms URL you are supplying in a wms viewer (e.g. ArcGIS Explorer ).
To your questions:
1)try just adding the http:// to your url, without the localhost
2)A WMS layer can have any projection, it depends solely on the projection in which it was published. Information about a specific WMS's projection should be found in metadata.
3)If the two layers have the same projection, you do not need to do anything. If you want to use two layers in different projections in one map, one of the layers must be reprojected. In pure OpenLayers, this is done by specifying the projection parameter for each layer and then specifying the displayProjection parameter for the map. The layers will automatically be reprojected. However, reprojection takes some time and it increases the load time VERY significantly. It is better to avoid reprojection on-the-fly, if possible. You can either reproject the source data of one of the layers and use reprojected data. Of course, this is not possible for a WMS, so you should consider using a different data source. If you want a background map, you can donwload OpenStreetMap data, reproject them to your desired projection, and then use them with the other WMS you want to use.
Hope at least some of this helps :-)

DocsUploadView and setOAuthToken causing "undefined Dismiss" error

I'm building a webapp where a user can Authorize via OAuth2 and choose/upload files from their own Drive for later use. Essentially we're just storing the file ID and using the API to access them later. Everything is working fine when I use .setAuthUser() and require users to be logged in independent of our app, but when we use .setOAuthToken() instead only the file picker works — the DocsUploadView panel returns an "undefined" error.
This behavior is consistent across Firefox/Chrome/Safari and with or without a current user login. It's always able to see files, never able to upload them. We are requesting full drive scope but even with that we're seeing errors.
For now we're just using setAuthUser as a workaround but this causes extra steps and a few problems when a user isn't logged in. Is it possible to use setOAuthToken with DocsUploadView?
The picker builder code I'm using is below, with IDs and tokens in the same format I'm using but altered for security.
Thanks!
var view = new google.picker.View(google.picker.ViewId.DOCS);
var uploadview = new google.picker.DocsUploadView();
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.MINE_ONLY)
.disableFeature(google.picker.Feature.NAV_HIDDEN)
.disableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId('987654321098')
.setOAuthToken('ya31.AIER6DRhxRgRsT0SoGPoaxPMhDd0n3OHKj43SJaG5kFndZ52')
.addView(uploadview)
.addView(view)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
[cross-posted at: https://groups.google.com/d/topic/google-picker-api/p9whgDscUrQ/discussion]
The Picker API doesn't currently support uploads using OAuth tokens. I filed an internal feature request for this to be implemented, but for the moment you should keep relying on your workaround.
This even SOUNDS stupid, but what about order of execution in the chaining?
.addView(uploadview)
.addView(view)
becomes
.addView(view)
.addView(uploadview)
Another thing I might suggest here is to enable multi_select on the picker
enableFeature(google.picker.Feature.NAV_HIDDEN)
enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
, just to test that there's not a bug in dependency on either of those features.