Find polygon for place in KML - javascript

NOTE: Please make sure you read my updates at the bottom!!
I have a KML file that I load 'onto' a Google Map; I also have a searchbox where users can search for a city. When the city is found I place a marker which, in most (if not all) cases should fall in one of the polygons defined in the KML.
I can click a polygon and it shows an info-popup with the areacode for that area; however: when a marker is placed I would like to have this info-popup shown automatically (and possibly other(s) that are shown before placing the marker hidden).
I have looked over the Maps V3 documentation but was unable to find anything. Is this possible?
You can view the project at http://netnummer.robiii.me, the source can be found at https://github.com/RobThree/NetnummersNL
The relevant (snippet of) code is:
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
if (!place.geometry)
return;
// Remove any existing markers
for (var i = 0, marker; marker = markers[i]; i++)
marker.setMap(null);
markers = [];
// Create a marker for place.
var marker = new google.maps.Marker({
map: map,
icon: image,
title: place.name,
position: place.geometry.location
});
markers.push(marker);
// ... Here I should figure out in which polygon the marker is positioned
// ... and preferrably open/display the info-window which is shown when a
// ... polygon is clicked.
// Scroll (pan) to marker
map.panTo(place.geometry.location);
});
Also, as a side-question: autocomplete.getPlace(); always returns an object; what is the best way to find out if the object is an actual (useful) place? When I search for xxxx for example, getPlace() returns Object {name: "xxxx"}, an actual result (like searching for Amsterdam) returns Object {address_components: Array[4], adr_address: "<span class="locality">Amsterdam</span>, <span class="country-name">Nederland</span>", …}. I currently use if (!place.geometry) to find out if the place is useful / an actual place; however I guess there's a better way ('best practice'?) to do this?
Edit 1: just stumbled across With Google Maps API V3, determine if a marker is inside a KML Layer boundary. Currently looking into it. However, I should probably note that the KML is hosted by a 3rd party and updated at will by them; as I use static site hosting I prefer not to have a separate process to extract the coordinates from polygons from the KML file. I prefer to "read" the KML (in)directly.
Edit 2: I moved from (direct) KML to a FusionTables based solution. I can now "highlight" polygons where the place is in. Now all I (still) need is a way to figure out how to show it's InfoWindow. I'll look into that tomorrow; it seems I need to query (again) into a DataTable or something and get the label info that way.
Edit 3: Solved!

I should've been in bed by now (see edits and comments) but hey... I just don't let go that easily...
So here's what I did:
Move from (direct) KML to Fusion Tables (Resulting html)
Fire off an extra query using Google Visualization's datatables to get the data I want for the specific region (Resulting html)
Use the place variable I already had for lat/lng and name and show infowindow
...
Profit!
I purposely linked above links to specific diffs or files of a specific version so later changes/updates won't mess with this answer. It's a bit too much to post all specifics in this post but I hope this helps someone.
The final result can be seen here.

Related

javascript/ionic - Google Maps not removing directions

directionDisplay.setMap(null);
is not working at my situation.
Working in ionic/corodova environment, Xcode ios project.
The app is the same concept of Uber.
An app needs to pull data from the database every 3 seconds to check if there is new order. If there is new order it gets location of an order and location of a driver.
Then puts the markers and shows directions between them.
There is an interval that watches if the order have been completed, once it is completed it should remove the directions and markers. Markers are removed but the directions are staying on the map.
The code is very long and StackOverFlow not letting me insert it here.
The console says that it cant find variable, that is strange since the variable is there.
Let me know where else I can share the code to show.
This code fixed the problem:
var gmarkers = [];// opening array
function removeMarkers(){ // creating function to remove everything on the map including the markers and directions
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
... other code is here
//inserting near the variable directionDisplay the code to push it into array
var directionsDisplay = new google.maps.DirectionsRenderer;
gmarkers.push(directionsDisplay);

Draw a polyline based on user click and/or current user location

Currently I'm building a webapp to draw my city public transport routes (Which aren't in Google Maps). I'm using encoded polylines to display them and have created a <ul> from which they can be manually selected. It works fine but need to add more functionality.
What I want is that when a user clicks a point on the map or uses the geolocation function, the routes (As predefined polylines) that get pass nearby get drawn.
I've read the containsLocation() documentation but it doesn't seem to do the trick. Is there a specific library that I'm missing to do this?
Already searched a lot and can't find what I want.
Currently this is the code that draws the polyline (When called from a <li onclick='drawfunction()';> element):
function (drawingfunction) {
var map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
var decodedPath = google.maps.geometry.encoding.decodePath('encodedpolyline');
var decodedLevels = decodeLevels('encodedlevels');
}
I think you want to check out the google.maps.geometry.poly.isLocationOnEdge function.
Assuming your route Polylines are in a routes array:
for (var i = 0; i < routes.length; i++) {
var matching = google.maps.geometry.poly.isLocationOnEdge(
location, routes[i], TOLERANCE);
routes[i].setOptions({
strokeColor: matching ? MATCHING_COLOR : DEFAULT_COLOR,
strokeOpacity: matching ? 1 : .7
});
}
You'll want to play around with the tolerance parameter to find a suitable size for your click target.
It might be quite slow if you have a lot of routes (or complex routes). If it is, then you'll want to investigate a data structure like a quad tree to narrow down the routes before calling isLocationOnEdge.

Adding Google Maps Marker in localStorage

Is there a way to add a marker created by a user to localStorage? I would like the retrieve the same coordinates of the marker that was added by the user if the browser refreshes or closes. It seems like localStorage can help achieve that.
I am trying something as follows, which doesn't seem correct. Please note that I am fairly new to JavaScript.
google.maps.event.addListener(marker, "dragend", function() {
localStorage.setItem('marker',true);
localStorage.getItem('marker');
});
I think it may be setting the marker in localStorage, but I can't see it upon page refresh.
Thank you.
If you try to store the marker itself you will get an error "Converting circular structure to JSON", even after stringifying it. Plus, it will store extra data which you may not need. I recommend you to store in the browser as minimum as possible of data due to space limitations.
What you can do instead is create your datatype to holds the info of marker (lat and long) and store this object. See the following....
var latlng = new google.maps.LatLng(42.123456789, -36.123456789);
var marker = new google.maps.Marker({
position: latlng
});
var newMarker = {Lat: marker.position.lat(), Lng: marker.position.lng()};
localStorage["marker1"] = JSON.stringify(newMarker);
console.log(localStorage["marker1"]);
play with it here: http://jsfiddle.net/94qhJ/

JavaScript, Maps API: Click one of many elements, extract a portion of its name, and apply it in a function

Forgive me if I misuse any technical terms; I'm still fairly new to programming. I'm creating a map with Google Maps API 3.12 that will include a menu of 600 entries with addresses, but this is mostly a JavaScript issue. Each address is clickable (in a menu) that will cause the map to go to its respective marker. Alternately, clicking a marker will send users to that place in the menu.
I started just going through and writing each out, but I've quickly realize this will send my code well over 20,000 lines, which will both slow my code and be torturous for me.
Here is some of the initial code:
function initialize() {
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var latlng1 = new google.maps.LatLng(41.88267,-87.623758); //etc for all 600 addresses
var marker1 = new google.maps.Marker({
position: latlng1,
map: map
}); //etc for all 600 markers
var contentString1 = '<div>blahblahblah</div>'; //gives content specific to place1.
var infowindow = new google.maps.InfoWindow();
}
The following is where I'd like to save on lines. Instead of copying and pasting this entire code 600 times for place/marker/contentString1 and 2 and 3, up to 600, I'm trying to figure out a way to write this function once for all of them:
google.maps.event.addDomListener(document.getElementById("place1"), "click", function() {
map.setCenter(marker1.getPosition());
map.setZoom(15);
infowindow.setContent(contentString1);
infowindow.open(map, marker1);
window.location = '#map-canvas';
});
This code makes it so I can click on the menu, and the map will jump to the corresponding marker and also pop up an info window. It is always just, "click placeX, go to markerX at latlngX with the respective infowindow content," but I am having the hardest time figuring something out that will be universal.
Could something like the following work? My theory is that clicking on any place in the menu could trigger this function rather than having to click on a specific place. This will then pull out the appending number of the specific place that is clicked (I call that number x below), and apply it to the function below. If I changed the place elements from IDs to class elements, would this make it possible? I'm not even sure how to do it then. Would that in turn create a different problem with the code I already have?
google.maps.event.addDomListener(document.getElementById("place"), "click", function (x) {
map.setCenter("marker" + x.getPosition());
map.setZoom(15);
infowindow.setContent("contentString" + x);
infowindow.open(map, "marker" + x);
window.location = '#map-canvas';
});
I've been trying variations on this for days now, but I can't get anything to work. I'm not sure if it's issues of theory, scope, syntax or all of the above. Any ideas? Thanks.

Delaying execution of Javascript function relative to Google Maps / geoxml3 parser?

I'm working on a implementing a Google map on a website with our own tiles overlays and KML elements. I've been previously requested to create code so that, for instance, when the page is loaded from a specific URL, it would initialize with one of the tile overlays already enabled. Recently, I've been requested to do the same for the buildings which are outlined by KML elements so that, arriving at the page with a specific URL, it would automatically zoom, center, and display information on the building.
However, while starting with the tile overlays work, the building KML does not. After doing some testing, I've determined that when the code which checks the URL executes, the page is still loading the KML elements and thus do not exist for the code to compare to or use:
Code for evaluating URL (placed at the end of onLoad="initialize()")
function urlClick() {
var currentURL = window.location.href; //Retrieve page URL
var URLpiece = currentURL.slice(-6); //pull the last 6 digits (for testing)
if (URLpiece === "access") { //If the resulting string is "access":
access_click(); //Display accessibility overlay
} else if (URLpiece === "middle") { //Else if the string is "middle":
facetClick('Middle College'); //Click on building "Middle College"
};
};
facetClick();
function facetClick(name) { //Convert building name to building ID.
for (var i = 0; i < active.placemarks.length; i++) {
if (active.placemarks[i].name === name) {
sideClick(i) //Click building whose id matches "Middle College"
};
};
};
Firebug Console Error
active is null
for (var i = 0; i < active.placemarks.length; i++) {
active.placemarks is which KML elements are loaded on the page, and being null, means no KML has been loaded yet. In short, I have a mistiming and I can't seem to find a suitable place to place the URL code to execute after the KMl has loaded. As noted above, I placed it at the end of onLoad="initialize()", but it would appear that, instead of waiting for the KML to completely load earlier in the function, the remainder of the function is executed:
onLoad="initialize()"
information(); //Use the buttons variables inital state to set up description
buttons(); //and button state
button_hover(0); //and button description to neutral.
//Create and arrange the Google Map.
//Create basic tile overlays.
//Set up parser to work with KML elements.
myParser = new geoXML3.parser({ //Parser: Takes KML and converts to JS.
map: map, //Applies parsed KML to the map
singleInfoWindow: true,
afterParse: useTheData //Allows us to use the parsed KML in a function
});
myParser.parse(['/maps/kml/shapes.kml','/maps/kml/shapes_hidden.kml']);
google.maps.event.addListener(map, 'maptypeid_changed', function() {
autoOverlay();
});
//Create other tile overlays to appear over KML elements.
urlClick();
I suspect one my issues lies in using the geoxml3 parser (http://code.google.com/p/geoxml3/) which converts our KML files to Javascript. While the page has completed loading all of the elements, the map on the page is still loading, including the KML elements. I have also tried placing urlClick() in the parser itself in various places which appear to execute after all the shapes have been parsed, but I've had no success there either.
While I've been intending to strip out the parser, I would like to know if there is any way of executing the "urlClick" after the parser has returned the KML shapes. Ideally, I don't want to use an arbitrary means of defining a time to wait, such as "wait 3 seconds, and go", as my various browsers all load the page at different times; rather, I'm looking for some way to say "when the parser is done, execute" or "when the Google map is completely loaded, execute" or perhaps even "hold until the parser is complete before advancing to urlClick".
Edit: Here are links to the map with the basic form of the issue found above. Since I've been developing the next update to the map on a test server, facetClick() is not part of this live version and I instead use its output function sideClick(); however the error is still the same in this arrangement:
active is null
google.maps.event.trigger(active.gpolygons[poly],'click');
Map: http://www.beloit.edu/maps/
Map w/Accessibility: http://www.beloit.edu/maps/?access
Map w/Building Click: http://www.beloit.edu/maps/?middle
EDIT: Spent most of my day working on rebuilding the functionality of the parser in Javascript and, low and behold, without the parser it works just fine. I figure that is obvious as I have to define each shape individually before the code, rather than waiting for it to be passed along by the parser. It would seem the answer is "if you want unique URLs, drop the parser". >_<
I've come across a similar problem when dealing with waiting for markers and infoWindows to load before executing a function. I found a solution here ( How can I check whether Google Maps is fully loaded? see #Veseliq's answer) that using the google maps event listener function for checking when the map is 'idle', does the trick. I assume this solution would work for KML layers as well. Essentially what you will have to do is include the following at the end of your initialize function:
google.maps.event.addListenerOnce(map, 'idle', function(){
// do something only the first time the map is loaded
});
In the API reference ( https://developers.google.com/maps/documentation/javascript/reference ) it states that the 'idle' event "is fired when the map becomes idle after panning or zooming". However, it seems to hold true that it is also fires on initial page load after everything in the map_canvas has loaded. And by using the addListenerOnce call, you ensure that it is never executed again after the initial page load (meaning it won't fire after a zoom or a pan action).
Second option:
As I mentioned you can take the callback approach, I believe this will only call your urlClick function after completing the parsing. Here's how you should probably arrange your code to make it work:
function someFunction(callback){
myParser.parse(['/maps/kml/shapes.kml','/maps/kml/shapes_hidden.kml']);
callback();
}
and then in your initialize you will have:
someFunction(function(){
urlClick();
});
You will have to make your map and myParser variables global.
Resources: This link had an excellent and detailed brief on how callback functions work in javascript, http://www.impressivewebs.com/callback-functions-javascript/

Categories

Resources