2

My default Leaflet popups have a background color of white. When a user turns on dark mode, I want them all to turn black.

I'm looping over all of the popups, but for some reason they're not changing color. I've tried adding a custom class to the popup but that's not working either.

What am I missing to change the color of all popup wrappers dynamically?

.leaflet-popup-content-wrapper {
    background: white;
}
var wrapper = document.getElementsByClassName('leaflet-popup-content-wrapper');

for (var i = 0; i < wrapper.length; i++) {
    wrapper[i].style.backgroundColor = 'black';
}

Edit

I realized through XaC's answer below that I need to change all unopened popups. How would I go about this?

Updated Code

Here's the code I'm using. Switching classes works if I just use L.popup(),as the popups are open on the map. However, when using marker.bindPopup() it fails and the classes don't switch.

Nothing gets printed to the console when looping through either. Basically it looks like the popups don't even exist until the marker is clicked.

CSS

.light .leaflet-popup-content-wrapper {
    background: black;
}

.dark .leaflet-popup-content-wrapper {
    background: white;
}

Placing the markers

marker.bindPopup(popupContents(item), {
    closeButton: false,
    className: 'light'
}).addTo(layer);

Switching the classes

document.addEventListener('dark-mode-updated', event => {
    if (event.detail.text === 1) {
        var popups = document.getElementsByClassName('light');
        while (popups.length > 0) {
            
        // nothing prints here when using bindPopup() UNLESS a popup is open
        console.log(popups);
            
        popups[0].classList.replace('light','dark');
        }
    }
}
timgavin
  • 4,972
  • 4
  • 36
  • 48

1 Answers1

0

Your code works for me:

I put 3 popups and one linked to a marker, and they change colours when I call the function via a button:

function changecolour(){
            var wrapper = document.getElementsByClassName('leaflet-popup-content-wrapper');
        
            while( wrapper.length; i++) {
                wrapper[i].style.backgroundColor = colourList[colourIndex];
                colourIndex=(colourIndex+1)%colourList.length
            }
        }

Change colour

However, when creating a new popup, it starts with no background colour (wrapper[i].style.backgroundColor = <empty string>), but if you apply the change colour function to it, it will take a value.

To change the triangular tip, you can do the same with:

var tip = document.getElementsByClassName('leaflet-popup-tip');

Putting the colour to 'black' also works, so I'm not sure why your poups don't change colour.

To change the popups before they open:

you can create a custom class in css:

 .black-popup .leaflet-popup-content-wrapper {
    background: black;
    }   

and use it when you open a pop-up:

L.popup({className: 'black-popup'})

To change it dynamically, you can create another popup class with a different colour, and change the class:

var blackpopuplist = document.getElementsByClassName('black-popup');
        
while(blackpopuplist.length>0) {
        blackpopuplist[0].classList.switch('black-popup','red-popup');

(as JS is dynamic, the blackpopuplist.length will decrease to 0 as the classes are removed --- see this question How to change class for all elements retrieved by document.getElementsByClassName)

Popup bonded to markers

To assign a class to a popup linked to a marker:

either defined the class when creating the marker:

L.marker(latlong).addTo(this.map).bindPopup('Marker 2',{className: newClass}).openPopup();

or create the pop-up first, then bind it to the marker:

var popup2 = L.popup({className: newClass}).setContent('Pop up 2')
    
L.marker(latLong).addTo(this.map).bindPopup(popup2).openPopup();
        

as above, it you set the class, and change the colours before they are displayed, they will first be shown with the first colours. You could run the class switching function each time a popup is opened to make sure that they all have the right colours.

XaC
  • 432
  • 3
  • 9
  • Thank you. This made me realize what my problem is: I was expecting all popups to change color - even the unopened ones. Of course, only the open popups change. How can I change the colors of the unopened ones so they open with the new color? – timgavin Jan 19 '23 at 14:03
  • @timgavin by adding classes to the css and assigning them to the popups, you can set the colour when you create them. Then you can change the class if you want to change the colour afterwards. (see edit above) – XaC Jan 20 '23 at 09:14
  • Does that work for you? Because I've tried it as well and can't get it to work, and I think I see why: the popups are not in the document's HTML until they're created. On page load this wrapper is empty: `
    ` and it only populates when a popup opens. So it looks like there are no CSS classes to change until a popup is actually active?
    – timgavin Jan 20 '23 at 12:32
  • I created two CSS classes, red-popup and black-popup, and use two variables, newClass and oldClass to refer to them when I create the pop-ups: `L.popup({className:newClass})`. When I toggle the colour change, I switch the definitions of old and new I get all the elements by class name oldClass, then `.classList.replace(newClass,oldClass)`; It mostly works : apart if you create the popup first without adding it to the map. If you toggle the colours and after add it to the map, it has the original colours as it wasn't updated (but it will switch if you toggle again). – XaC Jan 20 '23 at 15:30
  • and I had to replace the `for` by a `while`, as the list of elements by class names gets reduced as your remove the classes from the elements. – XaC Jan 20 '23 at 15:34
  • I've updated my post with new code. This works when using `L.popup()` but fails when using `marker.bindPopup()` which is what I'm using. I apologize for not mentioning that earlier; I didn't realize there was such a difference! Really appreciate your help on this :) – timgavin Jan 20 '23 at 17:51
  • @timgavin it should be the same for popups on markers, you can either pass the class argument, or pass a L.popup(). See edit to the question above. – XaC Jan 23 '23 at 09:18
  • Unfortunately I can't get anything to work, but what you posted is correct and does answer the question. I'm just going to have to refresh the page. Thank you for all of your help! – timgavin Jan 28 '23 at 14:20