How do I resize the info window once it's opened? I have a hyperlink inside the window which generates an AJAX-request; on the callback I would like to resize the info window.
Check out the following. What happens is that i create an initial info window with minimal
info (see getInfoWindowHtml). The gmap.openInfoWindowHtml call provides for a callback which gets called after the infowindow opens. In that callback, make your ajax call and reset the window contents. There are two issues though:
i couldnt get the window to resize exactly to the returned content, so i just used a standard size (see the new GSize(300, 150) in the anonymous function returned by markerClickFn)
Im my case, if a marker is near the extremes of the image bounds, parts of the info window would be clipped. IOW, the map does not recenter to include the infowindow. I can probably fix this, but it has not been a pressing issue.
function markerClickFn(venue, latlng) {
return function() {
var title = venue.Name;
var infoHtml = getInfoWindowHtml(venue);
// need to zoom in
gmap.setZoom(13);
gmap.openInfoWindowHtml(latlng, infoHtml,
{
onOpenFn: function() {
var iw = gmap.getInfoWindow();
iw.reset(iw.getPoint(), iw.getTabs(), new GSize(300, 150), null, null);
$("#info-" + venue.Id.toString()).load("/Venue/MapInfoWindow/" + venue.Id);
}
}
);
};
}
function getSidebarHtml(venue) {
var url = "/Venue/Details/" + venue.Id; // actually should bring up infowindow
var html = "<li id='venue-" + venue.Id + "'>\n";
html = html + venue.Name + "\n";
//html = html + "<p class='description'>" + trunc(venue.Description, 200) + "</p>\n";
html = html + "</li>";
return html;
}
function getInfoWindowHtml(venue) {
var url = "/Venue/Details/" + venue.Id; // actually should bring up infowindow
var html = "<div id='info-" + venue.Id + "'><a href='" + url + "' class='url summary'>" + venue.Name + "</a></div>\n";
return html;
}
function addVenueMarker(venue) {
var icon = new GIcon(G_DEFAULT_ICON);
icon.image = "http://chart.apis.google.com/chart?cht=mm&chs=24x32&chco=FFFFFF,008CFF,000000&ext=.png";
var latLng = new GLatLng(venue.Lat, venue.Lng);
var marker = new GMarker(latLng, { icon: icon });
var fn = markerClickFn(venue, latLng);
GEvent.addListener(marker, "click", fn);
marker.event_ = venue;
marker.click_ = fn;
venue.marker_ = marker;
markers.push(marker);
return marker;
}
It looks like the only solution I found to resize the InfoWindow dynamically is to call the InfoWindow's setContent method. You'll need to pass in the HTML node or the HTML string. This basically redraws the InfoWindow. What it essentially does is close the current one and opens a new one. So, it'll see a flicker during the reloading of the content. This kind of sucks. It seems that Google deprecated their v2 API and made things really hard to do in the newer version. I think Google has hired a bunch of Sun Java developers across the street in Silicon Valley and they guys don't know how to provide simple to use API's like the Microsoft camp. Really frustrating!
It isn't possible to animate the resize of the info window, but there is a reset function. The documentation says that you can leave any parameter null, but if you leave the 'size' parameter null, you'll get an error. This means that you have to specify the size of the InfoWindow.
However, since that ruins the original point of dynamically resizing the window, I would strongly recommend simply closing the original info window and creating a new one - which is what the reset function will appear to do anyhow.
Related
I am trying to find whether the point lies on the line or not as below
function identifyFeatures(evt){
var extentGeom = pointToExtent(map,evt.mapPoint,10);
var filteredGraphics = dojo.filter(testLayer.graphics, function(gg) {
if(extentGeom.contains(gg.geometry.getExtent())){
return extentGeom.contains(gg.geometry.getExtent());
} else {
return gg.geometry.getExtent().contains(extentGeom);
}
});
var content = "";
content = "<i>Total Features: " + filteredGraphics.length + "</i>";
map.infoWindow.setContent(content);
map.infoWindow.setTitle("Identify Results");
var anchor = map.getInfoWindowAnchor(evt.screenPoint);
map.infoWindow.show(evt.screenPoint,anchor);
};
I am using contains method of extent and trying to check whether clicked
point extent is falling on line extent or line extent is falling on clicked
point extent.But if I click on the center of the line then only I am getting
features.
You can see the code fiddle
can any one suggest me is there any other way to check whether point lies on line or not?
You should just filter graphics if the extent of the point (padded with your extentToPoint() function) intersects() with the geometry of the line.
function identifyFeatures(evt){
var extentGeom = pointToExtent(map,evt.mapPoint,10);
var filteredGraphics = dojo.filter(testLayer.graphics, function(gg) {
return extentGeom.intersects(gg.geometry);
});
var content = "<i>Total Features: " + filteredGraphics.length + "</i>";
map.infoWindow.setContent(content);
map.infoWindow.setTitle("Identify Results");
map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.screenPoint));
};
see a working demo: https://jsfiddle.net/q68rzde2/1/
I have an Openlayers map with several WMS layers from which I want to request feature information through "getGetFeatureInfoUrl". Visibility of layers can be turned on/off in the layer tree. I'd like to, upon clicking somewhere in the map:
Get Feature Info ONLY for layers that are currently visible
and, if there are more than one layers at the chosen location, get the Feature Info for all of them.
I used the sample code from the OpenLayers website. I tried variants of this code bit
var url = layers[2].getSource().getGetFeatureInfoUrl(
evt1.coordinate, viewResolution, 'EPSG:3857', {
'INFO_FORMAT': 'text/html',
'FEATURE_COUNT': '300'
});
like
var url = layers[].getSource().getGetFeatureInfoUrl( or
var url = layers[1,2].getSource().getGetFeatureInfoUrl(, but either no Feature Info is delivered, or merely for the last layer - regardless of whether it is visible or not.
I created a JSFiddle with two sample layers here: http://jsfiddle.net/kidalex/j34xzaa3/5/
Similar questions were asked before, like here: https://gis.stackexchange.com/questions/114297/querying-multiple-wms-layers-in-ol3-and-adding-to-a-single-popup-window; but I cannot fathom how to apply the solutions (JS/OL newbie here).
You should iterate over your layers and only call getFeatureInfo if they are visible and not the base layer, try something like:
map.on('singleclick', function (evt1) {
document.getElementById('info').innerHTML = '';
var viewResolution = /** #type {number} */
(view.getResolution());
var url = '';
document.getElementById('info').innerHTML ='';
layers.forEach(function (layer, i, layers) {
if (layer.getVisible() && layer.get('name')!='Basemap') {
url = layer.getSource().getGetFeatureInfoUrl(evt1.coordinate, viewResolution, 'EPSG:3857', {
'INFO_FORMAT': 'text/html',
'FEATURE_COUNT': '300'
});
if (url) {
document.getElementById('info').innerHTML +=
'<iframe seamless src="' + url + '"></iframe>';
}
}
});
});
EDIT: grammar
I am trying to set up a way to click through a post to a point on the map. I want to have the same effect as this:
http://jsfiddle.net/ZkC5M/17/
But inside a stream it is a little bit different. The click builds a queue so that when you do click it, it will click through about as many times as posts load. which slows down the app drastically and I am having trouble finding the right function to pinpoint the correct marker.
This is a real time app built with Meteor and using Leaflet:
http://twitter-map.meteor.com/
locStream = new Meteor.Stream('loc');
markers = [];
locStream.on('update', function(data) {
markerIterate++;
// Sets Marker
var marker = L.marker([data.lat, data.lon], {icon: icon}, {title:"marker_" + markerIterate})
.addTo(map)
.bindPopup(contentString)
.on('click', function(e) {widgetFunc()}); // widgetFunc() is set off to trigger the template for twitter
//Creates template for feed twitter view
var feedString =
'<div class="tweet">'+
'<blockquote class="twitter-tweet" lang="en">' +
'' +
'</blockquote>' +
'<a class="goTo" id="marker_' + markerIterate + '" href="#">Find on map</a>' +
'</div>';
// Sets tweet into the feed area
$('#feed').append(feedString)
markers.push(marker);
//This is the code that I have been playing with. I got it to work to open only one post.
function markerFunction(id){
var markerID = markers[1].options.title;
if (markerID == id){
markers[1].openPopup();
};
}
// This builds a queue of clicks that slows the app down drastically
$("a").click(function(){
markerFunction($(this)[0].id);
});
});// End Stream
I am using the Geolocation Marker Script from the Google Maps Utilities Library V3 in order to display the position of a user.
What I want to achieve (I am a newbie to the Google Maps API!) is:
have the users current coordinates displayed (e.g. in a simple CSS container somewhere on the page)
connect an event to a marker. I should be triggered when the user is close.
Appreciate your help!
To display coordinates to the user, you would need a reference to a DOM Element. Then it's a simple matter of updating the content.
HTML On the Page
<div id="UserCoordinates">Waiting on GPS Position ...</div>
In Script
google.maps.event.addListener(GeoMarker, 'position_changed', function() {
var UserPosition = this.getPosition();
var DisplayElement = document.getElementById('UserCoordinates');
if(UserPosition === null) {
DisplayElement.innerHTML = 'Waiting on GPS Position...';
} else {
DisplayElement.innerHTML =
'Current Position: ' + UserPosition.toUrlValue();
}
});
This will show the user their current position as it changes. If you are going to continue using a full screen map, you'll probably want to implement the UserCoordinates div as a map control. The API Reference has a good overview and multiple examples on this.
Display an info window when the user is within X meters of a location
This is a little tricky because there are multiple scenarios to handle and you don't want the infowindow opening repeatedly as they move within your radius.
Distance calculation
I see you have a distance function in your code, but I recommend using the one in the Spherical Geometry library of the API. You just have to specifically load the library with your api script tag:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=true_or_false">
</script>
Then you need to add to the position_changed event handler:
var IsWithinRadius = false; //assume they start outside of the circle
var RadiusInMeters = 1000; //within 1 km
var LocationOfInterest = map.getCenter();
google.maps.event.addListener(GeoMarker, 'position_changed', function() {
var UserPosition = this.getPosition();
var DisplayElement = document.getElementById('UserCoordinates');
if(UserPosition === null) {
DisplayElement.innerHTML = 'Waiting on GPS Position...';
IsWithinRadius = false; //you don't know where they are
} else {
DisplayElement.innerHTML =
'Current Position: ' + UserPosition.toUrlValue();
var IsCurrentPositionInRadius =
Math.abs(google.maps.geometry.spherical.computeDistanceBetween(
UserPosition, LocationOfInterest)) <= RadiusInMeters;
var JustEnteredRadius = !IsWithinRadius && IsCurrentPositionInRadius;
IsWithinRadius = IsCurrentPositionInRadius;
if(JustEnteredRadius) {
//trigger action here.
alert("Within raidus");
}
}
});
I'm trying to add custom controls to a Google map using the API. I already have two custom controls added and they work just fine. I tried to copy and paste the code for a third control (changing the relevant variables of course) and I keep getting the above error (in the title).
Chrome console and Firebug don't seem to point to a particular problem (it breaks inside the google maps api code). By progressively commented out lines, I've narrowed it down to this particular line:
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(churchControlDiv);
The full code for adding the control is as follows:
function ChurchControl(churchControlDiv, map) {
churchControlDiv.style.padding = '5px 0px';
var churchControlUI = document.createElement('DIV');
churchControlUI.style.backgroundColor = 'white';
churchControlUI.style.borderStyle = 'solid';
churchControlUI.style.borderWidth = '1px';
churchControlUI.style.borderColor = 'gray';
churchControlUI.style.boxShadow = 'rgba(0, 0, 0, 0.398438) 0px 2px 4px';
churchControlUI.style.cursor = 'pointer';
churchControlUI.style.textAlign = 'center';
churchControlUI.title = 'Click to see Churches';
churchControlDiv.appendChild(churchControlUI);
var churchControlText = document.createElement('DIV');
churchControlText.style.fontFamily = 'Arial,sans-serif';
churchControlText.style.fontSize = '13px';
churchControlText.style.padding = '1px 6px';
churchControlText.style.fontWeight = 'bold';
churchControlText.innerHTML = 'Churches<br>แสดงจำนวนคริสเตียน';
churchControlUI.appendChild(churchControlText);
google.maps.event.addDomListener(churchControlUI, 'click', function() {
toggle(churches);
if (churchControlText.style.fontWeight == 'bold') {
churchControlText.style.fontWeight = 'normal';
} else {
churchControlText.style.fontWeight = 'bold';
}
});
google.maps.event.addDomListener(churchControlUI, 'mouseover', function() {
churchControlUI.style.backgroundColor = '#e8e8e8';
});
google.maps.event.addDomListener(churchControlUI, 'mouseout', function() {
churchControlUI.style.backgroundColor = 'white';
});
}
function initialize(){
map = new google.maps.Map(document.getElementById("map_canvas"), {
center: centerLatLng,
zoom: 7,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var churchControlDiv = document.createElement('DIV');
var churchControlDiv = new ChurchControl(churchControlDiv, map);
churchControlDiv.index = 3;
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(churchControlDiv);
}
Any ideas? Any reason why having 3 controls would be a problem?
I had the same error pop up on my console whilst following the tutorial for a different reason.
Rather than using default javascript DOM manipulation, I'd been using jQuery to create my elements, e.g.
var controlDiv = $('<div></div>');
var controlUI = $('<div class="alert alert-info"></div>');
controlDiv.append(controlUI);
var controlText = $('<div>Control text here</div>');
controlUI.append(controlText);
Doing this is fine, so long as you give the DOM node to the map (and not the jQuery element!) at the end, using controlUI[0] or controlUI.get(0), like this:
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlDiv[0]);
See also:
How to get the native DOM element from a jQuery object - jQuery FAQ
I followed the tutorial, which is very close to your code.
This line near the end needs to change
var churchControlDiv = new ChurchControl(churchControlDiv, map);
Replace churchControlDiv with churchControl or another name because churchControlDiv should not be overwritten.
See here http://jsfiddle.net/FTjnE/2/
I marked my changes with //CHANGED an alert for the click, and new map center
The general underlying cause of this issue seems to be the element or its properties being removed or otherwise made not present. Maps API is trying to find the zIndex in the style property.
I had this issue in a Vue app custom component that interacted with the Maps API controls. We resolved it by exercising more caution in the teardown of the component.
Basically you need to ensure that you don't add a null element to the control, and don't make the element or its properties null before removing it, by doing something funky with say, v-if.