Skip Navigation

[Resolved] I only want one map popup open at a time

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 -
- 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 -

Supporter timezone: Europe/London (GMT+00:00)

This topic contains 9 replies, has 2 voices.

Last updated by scottL-3 6 months, 1 week ago.

Assisted by: Nigel.

Author
Posts
#2696979

Tell us what you are trying to do?
Helping a customer via the Toolset Contractor Hub that is using Toolset Maps with Azure Maps. They only want one popup open at a time. Clicking a marker should close all open popups and then open the new popup for the clicked marker.

They'd also like to force the popups to stay inside the viewport and not need scrolling to be seen.

Is there any documentation that you are following?
Checked Toolset documentation. Azure Maps documentation has some ideas on how to handle the popups but only if you're creating and adding popups with their API, not with Toolset as they basically remove all popups before adding the new one. Is there a Toolset JS event we can hook to do that in that order?

Is there a similar example that we can see?
Most sites that use maps with popups have these kinds of enhancements to improve user experience. For example, Marriott's map search scrolls to the open popup and closes other popups when it opens a new one: hidden link

What is the link to your site?
hidden link

#2697032

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

Hi Scott

I just checked this on my local maps test site, and both of these features happen by default, namely that the marker pop-ups close automatically whenever another is opened, and the map moves to accommodate pop-ups as they are opened.

But that's with Google maps, so I guess Azure maps work differently.

In which case I would first see if it is possible to switch to using Google maps.

Otherwise, without studying the Azure Maps API documentation I can't say much about how to modify its behaviour.

Let me share some code that has been used in the past to add a click event listener to markers so that they open the location in Google Maps in a new window, which will give you some ideas of how to interact with the rendered maps and markers.

( function( $ ) {
	$( document ).bind( 'js_event_wpv_addon_maps_init_map_completed', function(){

		var mapID = 'map-1'; // Edit

		var marker = [], lat, lng, target;

		// Locate the markers and add click handlers to open required URL
		$('[data-marker]').each( function( i, e ){
			
			markerID = $(this).attr('data-marker');

			marker[i] = WPViews.view_addon_maps.get_map_marker( markerID, mapID );

			lat = marker[i].position.lat();
			lng = marker[i].position.lng();
			target = "<em><u>hidden link</u></em>" + lat + "," + lng;

			marker[i].addListener('click', function(){
				window.open( target , '_blank');
			});

		});

	});
})( jQuery );
#2697068

Thanks. I use Google Maps for all of my own Toolset Maps projects.. This client chose Azure and I'm trying to help them. I will ask if they can switch to Google.

Do you know if it is possible to use [wpv-post-ID] as part of the marker ID when markers come from a View in the Map block settings? If each marker has a unique ID, it will be much easier for me to come up with a way to close the unneeded marker(s) when a new one opens. I do that all the time with legacy maps and views but I'm not sure if it works with Blocks.

#2697069

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

I just checked, and while with the Map block it is possible to use wpv-post-id in the marker ID setting, because of the different context of where you add it, it appears to always render as the ID of the page where the block is inserted. It doesn't update with each iteration of the loop (because it isn't in the loop, in the same way that it is in the legacy editor where you add the marker shortcode to the output of the View loop).

The IDs for markers are unique, a counter is automatically appended in cases where it would be duplicated, so if you just use "marker" as the ID the actual values used will be "marker", "marker-1", "marker-2", etc.

It might help to know you can mix and match the block and legacy editors to get this to work.

You can use the block editor to create a View and to add a Map block. The Map block will create a map with some ID. Don't add any markers to the Map block. In the loop output of the View add a marker shortcode in the same way you would with the legacy editor, referencing the map ID from the Map block. That will add markers to the map, coming from the View, and give you more control.

#2697075

Thanks Nigel.

I found out they have to use Azure maps because of HIPAA. Microsoft will sign a BAA for HIPAA and Google will not. Since this is a medical business, they need the HIPAA compliance. So, no option to switch to Google Maps.

It is good that each marker has a unique ID. But if they are counter based instead of post ID based, it isn't easy to know which one's popup is the one that we want to keep and which to remove. Maybe I can do that with (self) based on the click though.

I know I can mix legacy and blocks but the markers are tied to the search results from the View so I'd probably need to convert the whole thing to legacy to get what I want. I'd be happy with that solution but not sure if they will. I'll find out.

If you can ask development whether they ever expect Azure maps to handle scrolling to popups and the ability to only open one popup at a time in Azure maps like happens in Google Maps already, I'd appreciate it. Apparently Microsoft's idea for how to do this is to only have one popup and reuse it for all markers by changing the marker content with javascript on marker click. Not a bad idea in terms of keeping the DOM small but rather different than Google's approach.

One other note: If I add content to the marker hint field in the map block, with Azure Maps (haven't tried with Google), the hints show all the time, not just on hover. This seems like a bug. See hidden link

#2697090

So ...

WPViews.view_addon_maps.get_map_marker() works fine in Google Maps. I use it all the time in other projects and you use it in the sample code you provided above. I use it this way so I don't have to specify the map id:
jQuery(document).on('js_event_wpv_addon_maps_init_map_completed', function (event, event_settings) {
console.log("Loaded...");
var twsmap = WPViews.view_addon_maps.get_map(event_settings.map_id);

Whether I use it my way or your way with the explicit map id, in Azure Maps, it results in "jQuery.Deferred exception: undefined is not an object (evaluating 'WPViews.view_addon_maps.get_map') "

It seems that Azure is handled rather differently than Google in Maps. I also see some classes that make me think you / Azure might be using Mapbox as part of the solution. Maybe I can use some Mapbox APIs as a way around this ...

#2697129

Further to this, I think I have the code figured out that will remove Toolset/Azure's on click methods and replace them with my method that closes all popups before opening a new one. But I can't make it work as long as Toolset Maps' WPViews.view_addon_maps.get_map( event_settings.map_id ); doesn't work for Azure maps. If you can get that bug fixed, I think I can solve this part. And from there I may also be able to solve the problem with opening a popup not scrolling the popup into the map viewport.

#2697934

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

Screenshot 2024-05-15 at 15.16.03.png

Hi Scott

I had the chance to speak with one of the developers about this this morning.

They said if I escalate as a feature request they can investigate the issue with the Azure pins not operating the same way as Google markers, but I expect that would involve too long a wait for you with your current project.

To be honest, nearly all of the questions about Maps we get relate to the Google API; questions about Azure are rare, and so I don't have the same level of info I can share as I normally would about using Google.

If you are still working on a solution yourself, I would direct you towards the file wp-content/plugins/toolset-maps/resources/js/wpv_addon_maps.js, which is where the key action happens, and where the WPViews.view_addon_maps object is set up, with methods like get_map and get_map_marker.

I spent quite a while looking into this today.

It was puzzling as to why the WPViews.view_addon_maps object (which has the methods like get_map and get_map_markers) wasn't available when using Azure, but it was when using Google.

If you examine that file I linked to, you'll see that almost all of the code is set up inside a function WPViews.ViewAddonMaps (which includes code triggering the js_event_wpv_addon_maps_init_map_completed event).

The function isn't called until the very end of the file, like so:

jQuery( function( $ ) {
	WPViews.view_addon_maps = new WPViews.ViewAddonMaps( $ );
});

So, the object WPViews.view_addon_maps is the result of executing the WPViews.ViewAddonMaps function.

The function may not have completed execution by the time the js_event_wpv_addon_maps_init_map_completed event is triggered, so the callbacks you add to that event may run before WPViews.ViewAddonMaps is complete, and therefore at that point WPViews.view_addon_maps would be undefined.

So, in practice it looks like the code relating to rendering the Azure map is quicker than the equivalent code using the Google API, and too quick for the WPViews.view_addon_maps object to be ready.

If you type WPViews.view_addon_maps directly into the console with the Azure maps page it will correctly show the object details, as per my screenshot, but that's because you typing into the console is slow enough.

A somewhat crude solution is just to add a little time delay to your callback, enough for the WPViews.view_addon_maps object to become ready, e.g.

jQuery( document ).on('js_event_wpv_addon_maps_init_map_completed', function(event, map){

    setTimeout( function(){
        console.log( WPViews.view_addon_maps );
    }, 1000 );
});

Adding a 1000ms delay meant that the object was available, so you can then make use of its methods.

If you want a slightly more robust solution, you can set up a polling function to keep retrying after shorter intervals, up to a maximum number of retries.

You can thank chatGPT for this suggestion:

function waitForWPViewsAddonMaps(retries, interval) {
    if (retries > 0) {
        if (typeof WPViews.view_addon_maps !== 'undefined') {
            console.log('WPViews.view_addon_maps is defined:', WPViews.view_addon_maps);
        } else {
            setTimeout(function() {
                waitForWPViewsAddonMaps(retries - 1, interval);
            }, interval);
        }
    } else {
        console.warn('WPViews.view_addon_maps is still undefined after maximum retries');
    }
}

jQuery(document).on('js_event_wpv_addon_maps_init_map_completed', function(event, map) {
    waitForWPViewsAddonMaps(10, 200); // 10 retries with 200ms interval
});

I hope that helps.

#2697944

I'd like to see this added as an enhancement request / bug for development to fix because it really should work the same way for both map providers (and any future map providers such as OSM).

In the meantime, THANKS! I was headed down exactly the same road as you took and had read through the js files but hadn't yet tried the delay. I will experiment with various durations in the simple timeout approach first to see if I can get a good enough work around that way for now.

#2698213

So close ...
I can get the map object by using the delay but it doesn't behave like the atlas.Map object from Azure Maps or your markers aren't done using their markers API ...

I get the map with
var map = WPViews.view_addon_maps.get_map(event_settings.map_id);

But if I then try to get the markers with
var markers = map.entities.get({ type: 'marker' });

I get
TypeError: undefined is not an object (evaluating 'map.entities.get')
in the console.

I may have to give up on this problem as it is so different from using Google Maps. I do notice in the Views editor that the front end events button in the js editor specifically says "Google Maps", not "Maps". It seems like Azure Maps are not nearly as developed and supported in Toolset Maps. Not an issue for my own clients as I always use Google Maps but for this project to support someone else's project for their client that requires Azure Maps, it has created constraints we can't seem to get past.

Thanks for helping as much as you have. If you have more ideas on above issue and how to get the proper Maps object and markers let me know.