Remove "X" from Google Maps infoWindow [duplicate] - javascript

From what I see, in v2 of GMaps API there was a property "buttons" of the InfoWindow object that one could define in a way that given InfoWindow has no close button:
marker.openInfoWindowHtml("No Close Button",{buttons:{close:{show:4}}});
The above however does not apply for v3. Does anybody know a way to do it? I read about an utility that replaces InfoWindow called InfoBox but it has not been developed for the past 2 years. I'm currently using the latest 3.13 version of Gmaps v3 API.
A workaround with jQuery is acceptable, if there is no better solution.

You can also do it through the css.
.gm-style-iw + div {display: none;}
edit january 2019
as #antmeehan said in the comment,
Google have changed the HTML, and the close button is now a button element rather than a div
So the css code to hide the "x" button is now:
.gm-style-iw + button {display: none;}

Update
Displaying a <div> on top of a google map is straight forward :
example css:
div.info {
position: absolute;
z-index: 999;
width: 200px;
height: 100px;
display: none;
background-color: #fff;
border: 3px solid #ebebeb;
padding: 10px;
}
A info class <div> somewhere in the markup :
<div id="myinfo" class="info"><p>I am a div on top of a google map .. </p></div>
Always nice to have a short reference to the div :
var info = document.getElementById('myinfo');
The more tricky part, showing the <div>, how and when - here I just assign a click handler to the map (after it is created) and show the info <div> at mouse location XY inside the map :
google.maps.event.addListener(map, 'click', function(args) {
var x=args.pixel.x; //we clicked here
var y=args.pixel.y;
info.style.left=x+'px';
info.style.top=y+'px';
info.style.display='block';
});
What you gain with this is, that the info <div> follows you around on the map, every time you click.
You will need more styling so it suits your need, eg so it "looks like an InfoBox", but that should be easy to find out, I am not a librarian :)
And maybe later on something to close the info with, but that you didn't want in the first place :)
Original answer
You cant! There is no way to do this in the current v3.13 InfoWindow options.
A workaround is to disable the image containing the X :
<style>
img[src="http://maps.gstatic.com/mapfiles/api-3/images/mapcnt3.png"] {
display: none;
}
</style>
But this is in no way advisable!
src="http://maps.gstatic.com/mapfiles/api-3/images/mapcnt3.png is just what the infowindow is referring to today. Tomorrow, or in a month, or in a year, this image-reference for sure has changed. As you can see if you search for similar "solutions", made over time - like this. They are all broken today, eg the effort is meaningless.
I think there is extremely good logic in google "refusing" to follow the request for hiding the close-button. If you not need a close-button, what do you need an InfoWindow for anyway? When you are better off just to show a <div> on the map.

if using jquery just add this
$(".gm-style-iw").next("div").hide();

To extend on Louis Moore's answer, you can also center the text after removing the close button:
.gm-style-iw + div {display: none;}
.gm-style-iw {text-align:center;}
Without Centering:
With Centering:

Thanks Tushar, but also you need put this code in event handler
google.maps.event.addListener(infowindow, 'domready', function(){
$(".gm-style-iw").next("div").hide();
});

I used the answer given by Tushar Gaurav, but expanded it a little...
$(".gm-style-iw:contains(" + infoText + ")").css("left", function() {
return ($(this).parent().width() - $(this).width()) / 2;
}).next("div").remove();
That will remove the X from an infowindow with the text in infoText, and then recenter the text as it's off-center after removing the close button.
Just adding this for anyone else who stumbles across this page as I did.

It should be .gm-style-iw > button to avoid other custom buttons we might have within the box to be hidden too:
.gm-style-iw > button {
display: none !important;
}

closeBoxURL: ""
as stated before doesn't apply for InfoWIndow. This is an option on the InfoBox.
You may for example use this CSS workaround to remove the X, and the surrounding clickable button:
.gm-style-iw + div {
display: none;
}
And as davidkonrad said. This is a workaround on the code as it is today. It will likely be changed.

My own way (without Jquery) and with realign to the center of the infoWindow:
var content = document.querySelector('.gm-style-iw');
content.parentNode.removeChild(content.nextElementSibling);
content.style.setProperty('width', 'auto', 'important');
content.style.setProperty('right', content.style.left, 'important');
content.style.setProperty('text-align', 'center', 'important');

This works
.gm-style-iw > button {display: none !important;}

My solution:
google.maps.event.addListener(marker, 'click', function() {
var wnd = new google.maps.InfoWindow({
content: "<table id='viewObject' >...</table>"
});
google.maps.event.addListener(wnd, 'domready', function(){
$("#viewObject").parent().parent().next().remove();
});
wnd.open(map, marker);
});

============= HTML ==============
<agm-map #gm [latitude]="lat" [longitude]="lng" #AgmMap [fitBounds]="true">
<agm-marker
(mouseOver)="onMouseOver(infoWindow, gm)"
(mouseOut)="onMouseOut(infoWindow, gm)"
>
<div id="test">
<agm-info-window #infoWindow></agm-info-window>
</div>
</agm-marker>
</agm-map>
============= TS ==============
onMouseOver(infoWindow, gm) {
console.log(infoWindow);
if (gm.lastOpen != null) {
gm.lastOpen.close();
}
gm.lastOpen = infoWindow;
infoWindow.open();
setTimeout(() => {
var x = document.getElementsByClassName('gm-ui-hover-effect')[0].remove();
}, 10);
}
onMouseOut(infoWindow, gm) {
gm.lastOpen = infoWindow;
// infoWindow.close();
}

You can use this. This will not hide other images like zoom control, pan control etc.
on dom ready of info window you can use this.
google.maps.event.addListener(infoWindow, 'domready', function () {
document.querySelector(".gm-style-iw").nextElementSibling.style.display = "none";
});

I can't find correct answer in here, so I fixed it myself. It will work well.
google.maps.event.addListener(infowindow, 'domready', function(){
$(".gm-style-iw").parent().find("button").removeAttr("style").hide();
});

.gm-style-iw + button {display: none !important;}

Anno domini 2021 this work better for me
button.gm-ui-hover-effect {
display: none !important;
}

I couldn't get any of the $(".gm-style-iw").next("div").hide(); answers to work even when calling the code after the DOM was loaded, since there was a delay between the code being called and the info window being created. What I did was create an interval that runs until it finds the info window and removes the "X" element. If there's a better way please tell me.
var removeCloseButton = setInterval(
function()
{
if ($(".gm-style-iw").length)
{
$(".gm-style-iw").next("div").remove();
clearInterval(removeCloseButton);
}
},
10
);

Using Archers method I need to do
$(".gm-style-iw").css("left", function() { //remove close and recenter
return ($(this).parent().width() - $(this).find(">:first-child").width()) / 2;
}).next("div").remove();

google.maps.event.addListener(infowindow, 'domready', function() {
var iwOuter = jQuery('.gm-style-iw');
// Reference to the div that groups the close button elements.
var iwCloseBtn = iwOuter.next();
// Apply the desired effect to the close button
iwCloseBtn.remove()
});
As there is no option to hide this by API parameter, you have to find the element by targeting the content window and remove it.
Hope this helps :)

in jQuery's gmap3 plugin this can be accomplished using
google.maps.event.addListener($('#map').gmap3({get:{name:"infowindow"}}), 'domready', function(){
$(".gm-style-iw").next("div").remove();
});

May 2021 : Add this in your CSS:
button.gm-ui-hover-effect {
visibility: hidden;
}
This worked perfectly with Maps API v3.43

Inspect it - it's a div with a class of close on it - you can target it with CSS and set it to display: none;

You can just use the option
closeBoxURL : ""
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html
From Google Documentation
closeBoxURL | string | The URL of the image representing the close box. Note: The default is the URL for Google's standard close box. Set
this property to "" if no close box is required.
Example
var infowindow = new google.maps.InfoWindow({
closeBoxURL: "",
closeBoxMargin : ""
});

You can set "closeBoxURL" property of the Info Window to "" and it will make the button disappear.
var infowindow = new google.maps.InfoWindow({
content: contentString,
closeBoxURL: ""
});

Related

MapBox: Markers not showing clickable cursor on mouseover

I am moving from leaflet+cloudmade to mapbox and have been doing minor rewrites to my code where necessary. I am refreshing my map and in my previous installment it was easiest to add each marker in to it's own layer and then on refresh to remove all layers and redraw the markers.
Here is my current code:
function setLeafletMarker(lat, lng, iconType, popupHTML) {
popupHTML = typeof popupHTML !== 'undefined' ? popupHTML : "";
var LamMarker = new L.Marker([lat, lng], { icon: iconType }); //.on('click', markerClick); ;
markers.push(LamMarker);
LamMarker.bindPopup(popupHTML);
map.addLayer(LamMarker);
}
I suspect this has something to do with the problem, which is that when I put my mouse cursor over a marker, it stays as a hand (draggable) instead of changing to be a pointy finger, meaning the marker is clickable. Clicking works fine, but it's not very intuitive. How do I change the hand to pointy finger?
Ran into the same problem also. Did a quick check of CSS on the mapbox site, and they seem to fix it using a css rule in their sitewide css file (not map specific). I was able to fix the problem using the same approach, by adding this to my sitewide css.
.leaflet-overlay-pane path,
.leaflet-marker-icon {
cursor: pointer;
}
I have compared the default leaflet.css with the default mapbox.css and leaflet includes this
.leaflet-clickable {
cursor: pointer;
}
while mapbox does not.
One way is you can just add the behavior to the mouseover and mouseout events:
LamMarker.on("mouseover", function(e) {
document.getElementById('map').style.cursor = "pointer";
}).on("mouseout", function(e) {
document.getElementById('map').style.cursor = "grab";
});
In the current mapbox api (2022) this works. I'm not sure if there is a smarter way to do this as the docs are terrible in this department.
map.on('mouseover', 'source-id', e => {
map.getCanvas().style.cursor = 'pointer'
})
map.on('mouseleave', 'source-id', e => {
map.getCanvas().style.cursor = ''
})
This assumes you are adding a source layer to your map as in this example
If your not using source layers, you can target your marker icon via css
.marker svg {
cursor: pointer;
}

Google Maps API V3 Add a button near to a polygon hovered

I'm working with Google Maps API V3, and I'd like to display a clickable image near to a drawed polygon when the mouse hovers it.
Until now, I'm able to create this event, but I have no idea how to display this image near to my polygon. Ideally, I'd like this image appears where the mouse entered in the polygon.
Here is a piece of my code, but it's just a try and the image is not displayed, so it is very incomplete (and maybe wrong). You can suggest me to do otherwise, Javascript is not my preferred language...
google.maps.event.addListener(polygon, 'mouseover', function(e) {
this.setOptions( {fillOpacity: 0.1} );
polygon["btnMyButtonClickHandler"] = {};
polygon["btnMyButtonImageUrl"] = MyImage;
displayMyButton(polygon);
});
function displayMyButton(polygon) {
var path = polygon.getPath();
var myButton = getMyButton(path.btnMyButtonImageUrl);
if(myButton.length === 0)
{
console.log("IN"); //Is displayed in the console
var myImg= $("img[src$='http://linkToMyImage.png']");
myImg.parent().css('height', '21px !important');
myImg.parent().parent().append('<div style="overflow-x: hidden; overflow-y: hidden; position: absolute; width: 30px; height: 27px;top:21px;"><img src="' + path.btnMyButtonImageUrl+ '" class="myButtonClass" style="height:auto; width:auto; position: absolute; left:0;"/></div>');
// now get that button back again!
myButton = getMyButton(path.btnMyButtonImageUrl);
myButton.hover(function() {
$(this).css('left', '-30px'); return false; },
function() { $(this).css('left', '0px'); return false; });
myButton.mousedown(function() { $(this).css('left', '-60px'); return false;});
}
// if we've already attached a handler, remove it
if(path.btnDeleteClickHandler)
myButton.unbind('click', path.btnMyButtonClickHandler);
myButton.click(path.btnMyButtonClickHandler);
}
function getMyButton(imageUrl) {
return $("img[src$='" + imageUrl + "']");
}
Thanks for your suggestions !
EDIT
#MrUpsidown, unfortunately no, click event can't be a solution, I really need your Something here div appears at mouseover.
I modified your code like this :
google.maps.event.addListener(polygonPath, 'mouseover', function (event) {
if( $("#map_overlay").css('display') == "none")
{
$("#map_overlay").css({
'position': 'absolute',
'display': 'block',
'left': event.Sa.pageX,
'top': event.Sa.pageY
});
}
});
The div appears when my mouse enter the polygon and don't move except if my mouse hovers the div (which hovers the polygon). On this case, the event seems called continuously. How can we avoid this and let the div at its inital position once the mouse enter the polygon ?
Here is your modified : fiddle
You need to create an element to hold your clickable image. Make it position:absolute; with a bigger z-index than your map container. To place it at a specific place, check the mouse position on your polygon mouseover event and set the element position accordingly. Hope this helps.
Edit: Yes, wrap it in a DIV is a good idea. Here is a simple fiddle to show the concepts. And sorry, of course it was mouseover and not mouseenter like I first wrote.
http://jsfiddle.net/upsidown/zrC2D/

My jquery loading overlay doesn't show up every

For whatever reason, my jquery loading overlay doesn't load at all under any circumstance even though the same code was working just days ago. Well, not the exact same code. I have been trying to get the overlay to resize with the window, and I have been trying different things, but I don't understand what I did that caused the overlay to never even show up? Here is the code that should attach to the overlay to the correct div...
function MRNSearchInternals()
{
//debugger;
var form = $("#MRNSearch");
$div = $("#TabView1");
var srlzdform = form.serialize();
var PopID = <% =PopID %>;
var options = [];
var $url = $("#target").attr("action");
$('<div id="overlay">').css({
position: 'absolute',
opacity: 0.2,
top : $div.offset().top,
left : $div.offset().left,
width : $div.offset().width,
height : $div.outerHeight(),
background: 'blue url(<%=Url.Content("~/images/ajax-loader.gif")%>) no-repeat center'
}).hide().appendTo($div);
$("#overlay").fadeIn();
$.post('<%:Url.Action("SearchByMRN", "PatientACO")%>', srlzdform, function (data)
{
DisplayDemographicSearch(data);
$("#overlay").fadeOut();
});
}
Notice how I create the div. I give it an id, and then I call it's css atribute. From there I set all the css attributes. I then attempt to call fadeIn, and fadeOut after the ajax call. Any body have any idea why this isn't working? Any help would be great.
Some More clarification
Also notice how I chose the div to overlay. I get a div id from my dom
$div = $("#TabView1");
Also, I looked the source, and I do have that particular div in there. So that is not the problem. Somehow or the other, it simply isn't showing up.
UPDATE: The DOM I get
Below is what is produced from the jquery code. It appears as though everything is being created fine. Note also, that display is set to none. That is what I would expect since I have the overlay fade out. My question is why does it never show up.
<div class="TabView" id="TabView1">
<div class="Tabs">...</Tabs>
<div class="Pages">
<div id="overlay" style="left: 114px; top: 205px; height: 452px; display: none; position: absolute; opacity: 0.2; background-image: url("/images/ajax-loader.gif"); background-attachment: scroll; background-repeat: no-repeat; background-position-x: center; background-position-y: center; background-size: auto; background-origin: padding-box; background-clip: border-box; background-color: blue;"/>
</div>
Well, the better way to create the overlay div would be
$('<div/>', {
id: 'overlay'
})
Does that solve the problem? Otherwise, the ID might not be created, or does it?
Update for the edit from your post: the "width" attribute is not set on the created overlay. What happens if that is added and set to e.g. 100px? It seems like there is something wrong with the setting of the width attribute (or the getting of the width attribute of $div).
Is this code called more than once? If so, are you removing #overlay somewhere?
Calling this code multiple times would create duplicate #overlay dom nodes which is a no-no and could explain why it doesn't work sometimes.
To remove it, change:
$("#overlay").fadeOut();
to:
$("#overlay").fadeOut('slow', function () {
$("#overlay").remove();
});
Your selector doesn't look right.
I would try:
$('#overlay').css. . . .
function MRNSearchInternals()
{
//debugger;
var form = $("#MRNSearch");
$div = $("#TabView1");
var srlzdform = form.serialize();
var PopID = <% =PopID %>;
var options = [];
var $url = $("#target").attr("action");
$('<div id="overlay">').css({
position: 'absolute',
opacity: 0.2,
top : $div.offset().top,
left : $div.offset().left,
width : $div.offset().width, //<- The problem is right here should be $div.width
height : $div.outerHeight(),
background: 'grey url(<%=Url.Content("~/images/ajax-loader.gif")%>) no-repeat center'
}).hide().appendTo($div);
$("#overlay").fadeIn();
$.post('<%:Url.Action("SearchByMRN", "PatientACO")%>', srlzdform, function (data)
{
DisplayDemographicSearch(data);
$("#overlay").fadeOut('slow', function () {
$("#overlay").remove();
});
});
}
Man. That was real hard to debugg. I wish Visual studio 2010 had better jquery debugging capability. Thankfully, the next version is supposed to be a better jquery debugger. But, the problem was the width attribute.

z-Index overlay in google maps version 3

I'm trying to get an overlay in google maps api v3 to appear above all markers. But it seems that the google api always put my overlay with lowest z-index priority. Only solution i've found is to iterate up through the DOM tree and manually set z-index to a higher value. Poor solution.
I'm adding my a new div to my overlay with:
onclick : function (e) {
var index = $(e.target).index(),
lngLatXYposition = $.view.overlay.getProjection().fromLatLngToDivPixel(this.getPosition());
icon = this.getIcon(),
x = lngLatXYposition.x - icon.anchor.x,
y = lngLatXYposition.y - icon.anchor.y
$('<div>test</div>').css({ left: x, position: 'absolute', top: y + 'px', zIndex: 1000 }).appendTo('.overlay');
}
I've tried every property I could think of while creating my overlay. zIndex, zPriority etc.
I'm adding my overlay with:
$.view.overlay = new GmapOverlay( { map: view.map.gmap });
And GmapOverlay inherits from new google.maps.OverlayView.
Any ideas?
..fredrik
If anyone was having the same problem as I was, here is my problem and solution:
I needed an OverlayView which would add tooltips to markers, but my popup overlay kept showing behind the markers.
I implemented a subclass of the OverlayView as per the Google documentation:
https://developers.google.com/maps/documentation/javascript/customoverlays
When you write your custom OverlayView.prototype.onAdd function, you need to specify to which Pane to attach your overlay. I just copied the code without actually reading the surrounding explanation.
In their code, they attach the overlay to the overlayLayer pane:
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
But there are many different MapPanes you can use:
"The set of panes, of type MapPanes, specify the stacking order for different layers on
the map. The following panes are possible, and enumerated in the order in which they are stacked from bottom to top:"
MapPanes.mapPane (Level 0)
MapPanes.overlayLayer (Level 1)
MapPanes.markerLayer (Level 2)
MapPanes.overlayMouseTarget (Level 3)
MapPanes.floatPane (Level 4)
I wanted the overlay to hover over all other info on the map, so I used the floatPane pane and problem solved.
So, instead of :
this.getPanes().overlayLayer.appendChild(div)
you use this :
this.getPanes().floatPane.appendChild(div);
You can't change the zIndex of an OverlayView (it has no such property), but it holds panes that contains DOM nodes. That's where you can use the z-index property;
...
lngLatXYposition = $.view.overlay.getPanes().overlayLayer.style['zIndex'] = 1001;
...
In order to be able to play around with the paneType of the mapLabel class, I added a paneType property to the MapLabel class from google utility library (https://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/maplabel/src/maplabel.js?r=303).
This is usefull to make the label not to be hidden by a polyline.
Please find the code additions to the mapLabel.js file.
MapLabel.prototype.onAdd = function() {
var canvas = this.canvas_ = document.createElement('canvas');
var style = canvas.style;
style.position = 'absolute';
var ctx = canvas.getContext('2d');
ctx.lineJoin = 'round';
ctx.textBaseline = 'top';
this.drawCanvas_();
var panes = this.getPanes();
if (panes) {
// OLD: panes.mapPane.appendChild(canvas)
var paneType = this.get('paneType');
panes[paneType].appendChild(canvas);
}
};
MapLabel = function (opt_options) {
this.set('fontFamily', 'sans-serif');
this.set('fontSize', 12);
this.set('fontColor', '#000000');
this.set('strokeWeight', 4);
this.set('strokeColor', '#ffffff');
this.set('align', 'center');
this.set('zIndex', 1e3);
this.set('paneType', 'floatPane');
this.setValues(opt_options);
}
Sample code using the paneType:
var mapLabel = new MapLabel({
text: segDoc.curr_value.toFixed(0),
position: new google.maps.LatLng(lblLat, lblLng),
map: map.instance,
fontSize: 12,
align: 'center',
zIndex: 10000,
paneType: 'floatPane',
});
Thanks!
Setting z-index to 104 for the overLay layer seems to be the "magic" number" if you care about interacting with the markers (i.e. dragging markers). Any higher than 104 and you can not interact with the markers. Wondering if there is a less brittle solution...
Use panes.overlayMouseTarget.appendChild
If you want to allow your layer to be targetable through mouse clicks (and use events such as "click" or CSS pseudo ::hover) then you should add your overlay to the map using overlayMouseTarget
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(this.div_);
Also see:
https://developers.google.com/maps/documentation/javascript/reference?csw=1#MapPanes
Disclaimer: this is a dodgy solution that may stop working at any time and you definitely shouldn't use this in production.
For those looking for a quick and dirty solution, this CSS worked for me:
.gm-style > div:first-child > div:first-child > div:nth-child(4) {
z-index: 99 !important;
}
Use at your own risk!

I can add an overlay, but I can't remove it (jQuery)

This function adds an overlay with the following properties to the entire browser screen,
$('a.cell').click(function() {
$('<div id = "overlay" />').appendTo('body').fadeIn("slow");
});
#overlay
{
background-color: black;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: none;
z-index: 100;
opacity: 0.5;
}
And this function is supposed to remove it.
$('#overlay').click(function() {
$(this).fadeOut("slow").remove();
});
But it seems to do absolutely nothing and now my page is stuck with a black overly over it. What's wrong with the removal?
The problem is that when you're adding the click handler, there isn't any overlay, so you're adding the handler to an empty set of elements.
To fix this, use the live method to bind your handler to all elements that match #overlay, whenever they are created.
Also, fadeOut is not a blocking call, so it returns before the element finishes fading out. Therefore, you're calling remove right after the element starts fading out.
To fix this, use fadeOut's callback parameter to call remove after the animation finishes.
For example:
$('#overlay').live(function() {
$(this).fadeOut("slow", function() { $(this).remove(); });
});
Here you go. This should fix the problem and let the overlay fade out before removing it.
$('#overlay').live("click", function() {
$(this).fadeOut("slow", function() { $(this).remove() });
});
Remove should be in the callback to fadeout, like so:
$('#overlay').live('click', function() {
$(this).fadeOut("slow", function() {
$(this).remove();
});
});
Try:
$('#overlay').live('click', function() {
$(this).fadeOut("slow").remove();
});
My recommendation is to use the jquery.tools overlay plugin. Your overlay will have a trigger (usually a button or link), but you can load or clear it with a javascript command, e.g.:
js:
var config = { closeOnClick:true, mask:{opacity:0.7, color:'#333', loadSpeed:1} }
$("#myTrigger").overlay(config); // add overlay functionality
$("#myTrigger").data("overlay").load(); // make overlay appear
$("#myTrigger").data("overlay").close(); // make overlay disappear
html:
<div id="myOverlay" style="display:none;">Be sure to set width and height css.</div>
<button id="myTrigger" rel="#myOverlay">show overlay</button>

Categories