The admin bar disappears when a leaflet map is empty but still displayed.

I'm not sure whether to file this as a bug for the Leaflet module or for Backdrop Core. 
The reason is that although it seems to be caused by Leaflet (or one of it's submodules), I'd expect Backdrop Core to be able to withstand it.

I noticed the admin bar disappearing in a more complex setup, so decided to test it with a 'clean' setup, so below is a recipe to reproduce the bug.

Unless noted otherwise, leave defaults as is.

Have administration bar enabled.
Install address field, geofield, leaflet, geocoder.
Enable address field, geocode, geofield, leaflet, leaflet more maps, leaflet views.
In leaflet more maps configuration enable bing road layer.
In geocode configuration set Google API Authorization Method to Google API key, Delay between Google geocoding requests (in milliseconds) to 200, check Cache empty results, check  Force re-geocoding

Create a content type, named Testleaflet.
Add an address field, named Address, and a geofield to that content type.
Set the geofield widget to geocode from another field, set geocode from field Address, geocoder Openstreetmap Nominatim.

Create a block view, name Leaflettest, showing content of type Testleaflet, set  Format Leaflet map with datasource content: geofield and map type Bing Road & satellite hybrid, include Fields address and geofield (hidden), Contextual Filter NID, when the filter value is not available provide default value Content NID from URL.

Create a layout override, named Maptest, using Moscone flipped template, path node/%, visibility condition node type is Testleaflet, add the view Leaflettest to the content region.

Now add content of type Testleaflet, named One. Set a valid address, and see it appear on the map when viewing the content.
Add another item of type Testleaflet, named Two. Leave the address empty or set an invalid address that can't be geocoded.
Now when viewing the item, there is a grey map-box having no markers (this is expected), but the administration bar has disappeared.

When checking the source code of the page, note that in the item One, there is a div with id admin-bar. Additionally, the div with class leaflet-control-scale-line has width set to some 'reasonable' number of pixels (probably under 200, seems dependent on the location and zoom level, initial value seems to be 85px)
In the source code of the page showing item Two, there is no div with id admin-bar. Additionally, the div with class leaflet-control-scale-line has width set to some 'insanely large' number of pixels (786627000 is what I saw in both Firefox and Chromium developer tools) The actual width of the div as shown by the developer tools is only 17895200px (in Firefox, in Chromium the value is 26843486.8, these values will probably be different at different screen resolutions and page zoom levels).

The expected behaviour is that the admin bar is still present and that the width of leaflet-control-scale-line is some 'sane' value (preferably less than or equal to the map width, definitely less than the viewport width).

This was tested in both the Firefox and Chromium browsers.

Should I file this bug under Backdrop Core or the Leaflet module?

Comments

indigoxela's picture

Hi Ernst,

there seem to be a lot of modules involved, so it's not clear which one causes the trouble. I don't think, it's core. But I also don't think it's Leaflet.

I verified with an empty map, which displays fine and doesn't interfere with the admin bar in any way.

The very first thing to inspect is the browser console (log). There must be some errors logged there.

Another thing to check: which jQuery version is active (that's set on admin/config/development/jquery).

Hi Indigoxela,

There is indeed an error logged in the browser console:

Uncaught Error: Attempted to load an infinite number of tiles
    _update GridLayer.js:665
    _setView GridLayer.js:574
    _resetView GridLayer.js:530
    onAdd GridLayer.js:162
    _layerAdd Layer.js:114
    fire Events.js:195
    _resetView Map.js:1198
    setView Map.js:206
    attach leaflet.backdrop.js:229
    jQuery 2
    attach leaflet.backdrop.js:83
    attachBehaviors backdrop.js:73
    each jQuery
    attachBehaviors backdrop.js:71
    <anonymous> backdrop.js:699
    jQuery 13
GridLayer.js:665:45
    _update GridLayer.js:665
    _setView GridLayer.js:574
    _resetView GridLayer.js:530
    onAdd GridLayer.js:162
    _layerAdd Layer.js:114
    fire Events.js:195
    _resetView Map.js:1198
    setView Map.js:206
    attach leaflet.backdrop.js:229
    jQuery 2
    attach leaflet.backdrop.js:83
    attachBehaviors backdrop.js:73
    each jQuery
    attachBehaviors backdrop.js:71
    <anonymous> backdrop.js:699
    jQuery 13

JQuery version is 3.

Do you think JQuery is the problem?

I'm surprised the problem did not reproduce for you. 

indigoxela's picture

I'm surprised the problem did not reproduce for you. 

I didn't use Geocoder. I hardly ever do, unless I need proximity search. You did a lot of things I never do with Leaflet.

Both, core and Leaflet work with jQuery 1, 3 and 4 without problems. That doesn't mean, every module does. But every module should work with jQuery 1 (legacy). Something to try out.

Empty field values usually hide the map in field display, only views can show the empty map. And that works just fine (if only Leaflet and Core involved).

It's still unclear, which module or setup part causes trouble here. I'd suggest to start on a fresh testing site and add things step by step until it breaks.

indigoxela's picture

A quick idea: did you use "Address" or "Address field"? Important difference.

Because if you used the latter, I'd suggest to get that out of the mix. Its maintenance is... ehm. And yes, Address field needs legacy jQuery.

I used the address field module, the field type is called 'address'. I see there also exists the address module which requires the address field module. Neither lists any jQuery version requirements in readme or .info files.

In any case, I tried changing the jQuery version and this did not change anything with this layout.

So next I'm going to try the constructive deconstruction on a fresh install.

I'm attaching the error as it appears with jQuery 1 below (the jQuery lines seem to have changed):

Uncaught Error: Attempted to load an infinite number of tiles
    _update GridLayer.js:665
    _setView GridLayer.js:574
    _resetView GridLayer.js:530
    onAdd GridLayer.js:162
    _layerAdd Layer.js:114
    fire Events.js:195
    _resetView Map.js:1198
    setView Map.js:206
    attach leaflet.backdrop.js:229
    jQuery 2
    attach leaflet.backdrop.js:83
    attachBehaviors backdrop.js:73
    each jQuery
    attachBehaviors backdrop.js:71
    <anonymous> backdrop.js:699
    jQuery 4
GridLayer.js:665:45
    _update GridLayer.js:665
    _setView GridLayer.js:574
    _resetView GridLayer.js:530
    onAdd GridLayer.js:162
    _layerAdd Layer.js:114
    fire Events.js:195
    _resetView Map.js:1198
    setView Map.js:206
    attach leaflet.backdrop.js:229
    jQuery 2
    attach leaflet.backdrop.js:83
    attachBehaviors backdrop.js:73
    each jQuery
    attachBehaviors backdrop.js:71
    <anonymous> backdrop.js:699
    jQuery 4

I don't have leaflet, but I have experienced random disappearances of the bar over the years. I quit spending time on it, but not before adjusting the css spacing, which did reduce the number of occurrences. I couldn't even nail one specific thing that causes it, but the quick fix is to have a shortcut to clear the caches, which brings it back every time. Sorry that doesn't solve the problem, but maybe helps a little.

Clearing the cache was one of the things I tried. This included truncating the cache tables that don't get cleared by the flush all caches button, as well as sessions and tempstore tables. This I followed up with restarting the web server (Apache)

It did not solve the issue, but it did help me to understand that the problem was to do with empty maps and not - as I thought at first - layout overrides for specific content types.

indigoxela's picture

To me this clearly looks like some wrong use of the Leaflet library at some point.

But the problem is not the empty map (alone), which works fine and never caused me trouble. Something else interferes and breaks the whole map.

BTW: an empty map displays with tiles without markers, not as grey area.

I belief, it has something to do with geocoding and what that returns.

indigoxela's picture

Update: I tried to use Leaflet and Geofield with Geocoder, but can't get geocoding from other field working at all. But at no point the map breaks. It just stays empty.

Is there really, really a reason to use geocoding at all? Why not using the leaflet_widget? That's so much easier and more reliable, than this geocode-from-other-field cruft. I also used Leaflet in D7, but never got this geocode-from-other-field stuff working. It's just too flaky and has always been.

Edit: I got geocoding working (finally) when using a simple textarea as source field and OpenStreetMap Nominatin as geocoder. Not that it works well in terms of good coordinate results, but it still does not break the map at any point, empty fields  or not.

I did now do the constructive deconstruction and indeed as long as I did not do the geocoding, I did not encounter the issue.

With the geocoding, with the setup of a leaflet view in a layout override, the problem returned when trying to display an empty map.

At some point I started to play around a bit more with the settings, and found that if I left the initial zoom level at 'use map defined settings' (which was what I'd been using the whole time), the problem appeared, if I however change that setting, the problem disappears for the empty map. 

This is of course problematic when trying to display a non-empty map, since the zoom level is no longer related to what is trying to be displayed.

In short, it seems that in the setup I use, the data is not validated enough before Leaflet tries to display it. The problem is not the empty data itself, but the resulting undefined map defined zoom level.

To test some more, I now created a new content type testforview, added a single geofield geo3  to it, no geocoding used. Then created a page view viewempty with path viewempty to display content of type testforview, set the format to leaflet map with fields title and geo3. Note that I did not create any content of type testforview so far. Now when I go to the path viewempty, I again get the same issue of disappearing admin bar and the Uncaught Error: Attempted to load an infinite number of tiles in the browser console. 

Edit: Changing the initial zoom level to something other than 'use map defined setting' does in this case also resolve the disappearance and error.

I did a bit more testing again using a new content type. It seems the problem with no sane default map zoom level is with all the maps from Leaflet More Maps (I did not try all of them, but everyone of those I tried exhibited the same issue. When using OSM Mapnik instead, you just get a map showing a seemingly empty bit of ocean west of São Tomé e Príncipe, without errors and the admin bar showing.

Additionally, if you define the view to use a map from Leaflet More Maps, you first get the error again, but if you then disable the Leaflet More Maps module without changing the definition of the view, you get just a grey map with the admin bar shown and just the following error:

Source map error: request failed with status 404
Resource URL: http://10.0.1.113/files/js/js_vmv6fUp6RdhSTQW69pfoOTPpr9Jxydaff8MCVp7gPcE.js
Source Map URL: leaflet.js.map;
indigoxela's picture

Wow, many thanks for keeping on digging. You finally found it!

Yes, now I can reproduce the problem, as soon as I switch to "Use map defined setting" in the view's zoom setting section.

And as I can reproduce it, I can fix it: https://github.com/backdrop-contrib/leaflet/issues/84

It's a one-liner bug fix.

If you don't mind testing - apply the patch and flush caches. That should do the trick.

Great.

I can confirm this fixed the issue.

Thanks.