1

I have a page with filters on top and a toggle between tile view or map view.

Every time a filter is changed I perform a search with AJAX and change the view using Mustache. On mobile the default view is the tile view with an icon on the bottom right to toggle the map. When my view is on the tile view, I change a filter (so the search triggers and filtered tiles show up), i then toggle to the map view and it is max zoomed out, and only the bottom left corner is not greyed out. It looks like this:

visual problem

When I load the page, and i immediately toggle to my map view, that is also the initial view I see. But if I then change my filters and perform the search again, the map will load correctly and works perfectly. But after switching to tiles, changing filters and going back to Map view, it breaks again.

This is the HTML holder for the map:

<div id="map_canvas"></div>

jQuery:

$(document).ready(function(){
    'use strict';

    curr_lang = $('#curr_lang').val();

    initializeElements();

    //Read the query parameters & set everything up according to it
    setupConfig(radiusSlider);
    //Setup the listeners for the freetext input search field
    setupFreetextField();
    setupInterestsField();
    setupLocationField();
    setupDaterangeField();
    setupMorefiltersField();
});

function initializeElements() {
    $(window).scroll(function() {
        var volunteer = $('#map_canvas');
        var offset = volunteer.offset();
        top = offset.top;
        state = $('.footer').offset().top;
        var bottom = $('#map_canvas').offset().top;

        if ($(window).scrollTop() + volunteer.height() + 134 > state) {
            volunteer.removeClass('fixed');
            volunteer.addClass('bottom');
        } else if ($(this).scrollTop() + 58 > bottom) {
            volunteer.addClass('fixed');
            volunteer.removeClass('bottom');
        } else {
            volunteer.removeClass('fixed');
            volunteer.removeClass('bottom');

        }

        //Enable search toggle menu icon
        if ($(window).width() <= 768) {
            var nav = $('.navbar-wrapper');
            var navOffset = nav.offset();

            var filters = $('.content-filters');
            var filtersOffset = filters.offset().top;

            var searchToggle = $('.search-filter-toggle');
            if ($(window).scrollTop() > filters.height()) {
                searchToggle.addClass('show');
            } else {
                searchToggle.removeClass('show');
                filters.removeClass('mobile-filters');
            }
        }
    });

    if ($(window).width() <= 768) {
        $('.search-filter-toggle').on('click',function(e) {
            var filters = $('.content-filters');
            filters.toggleClass('mobile-filters');
        });
    }

    $(window).resize(function() {

        var vacancyGrid = $('.vacancy-holder');
        var mapGrid = $('.map-holder');

        if ($(window).width() > 1227) {
            vacancyGrid.removeClass('hide-mobile');
            mapGrid.removeClass('show-mobile');
            $('#mapview').removeClass('hide-mobile');
            $('#gridview').removeClass('show-mobile');
            $(document.body).removeClass('map');
        }else if($(window).width() < 991){
        }
    });

    $('#mapview').on('click',function(e) {
        map.invalidateSize(false);
        var vacancyGrid = $('.vacancy-holder');
        var mapGrid = $('.map-holder');
        vacancyGrid.addClass('hide-mobile');
        vacancyGrid.removeClass('show-mobile');
        mapGrid.addClass('show-mobile');
        mapGrid.removeClass('hide-mobile');
        $('#mapview').addClass('hide-mobile');
        $('#mapview').removeClass('show-mobile');
        $('#gridview').addClass('show-mobile');
        $('#gridview').removeClass('hide-mobile');
        $(document.body).addClass('map');
        $("html, body").animate({ scrollTop: 0 });
    });

    $('#gridview').on('click',function(e) {
        var vacancyGrid = $('.vacancy-holder');
        var mapGrid = $('.map-holder');
        vacancyGrid.addClass('show-mobile');
        vacancyGrid.removeClass('hide-mobile');
        mapGrid.addClass('hide-mobile');
        mapGrid.removeClass('show-mobile');
        $('#mapview').addClass('show-mobile');
        $('#mapview').removeClass('hide-mobile');
        $('#gridview').addClass('hide-mobile');
        $('#gridview').removeClass('show-mobile');
        $(document.body).removeClass('map');
        $("html, body").animate({ scrollTop: 0 });
    });
}

function setupMap(vacancies) {
    //Destroy the map if it already exists
    if (map != undefined) {
        map.remove();
    }
    console.log("setting up the map...");
    //  this script enable displaying map with markers spiderfying and clustering using leaflet plugin
    var vacArr = [];
    var index = 0;
    if (vacancies.length > 0) {
        for (index = 0; index < vacancies.length; ++index) {
            var vacancy = vacancies[index];
            if (((vacancy.lat != 0) && (vacancy.lat !== undefined) && (vacancy.lat != null)) && ((vacancy.lng !=0) && (vacancy.lng !== undefined) && (vacancy.lat != null))) {
                var vacurl = vacancy.detailurl;
                var tempArr = [];
                tempArr.push(vacancy.lng);
                tempArr.push(vacancy.lat);
                tempArr.push(vacurl);
                tempArr.push(vacancy.name);
                tempArr.push(vacancy.orgname);
                vacArr.push(tempArr);
            }
        }
    }

    var tiles = L.tileLayer('//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        maxZoom: 18,
        attribution: '&copy; <a href="//openstreetmap.org/copyright">OpenStreetMap</a> contributors, Points &copy 2012 LINZ'
    });

    map = L.map('map_canvas', {
        center: L.latLng(51.260197, 4.402771),
        zoom: 10,
        layers: [tiles]
    });

    var mcg = L.markerClusterGroup({
        chunkedLoading: true,
        spiderfyOnMaxZoom: true,
        showCoverageOnHover: true //zoomToBoundsOnClick: false
    });

    var boundsarray = [];

    for (var i = 0; i < vacArr.length; i++) {

        var detailText = res.ViewDetail;
        var info ="<div id='infoId-' style=\"background:white\"> <a href=\""+vacArr[i][2] +"\"><h5>"+vacArr[i][3] +"</h5></a> <p class=\"marker_font\">"+vacArr[i][4]+"</p> <a href=\""+vacArr[i][2] +"\">"+detailText+"</a></p></div>";
        var title=vacArr[i][3];
        var marker = L.marker(new L.LatLng(vacArr[i][1], vacArr[i][0]), {
            title: title
        });

        boundsarray.push([vacArr[i][1], vacArr[i][0]]);
        mcg.on('clusterclick', function (a) {

            if('animationend zoom level: ', map.getZoom() >13)
            {
                a.layer.spiderfy();
            }
        });
        marker.bindPopup(info);
        mcg.addLayer(marker);
    }
    //console.log(boundsarray);
    map.fitBounds(boundsarray);
    map.addLayer(mcg);
}

EDIT: I added the complete code after trying to add map.invalidateSize(); on the map toggle function. But it results in the same. The setupMap() function is called at the end of my AJAX success method for searching. (The vacancies parameter is the result from my AJAX method and contains the information for the tiles and as well the lat/lon of the vacancy)

Dennis
  • 3,044
  • 2
  • 33
  • 52
  • 2
    I suspect this is a duplicate of https://stackoverflow.com/questions/10762984/leaflet-map-not-displayed-properly-inside-tabbed-panel . Why is `map.invalidateSize()` commented out? – IvanSanchez Jan 28 '19 at 20:54
  • I tried without the comment first, but adding that line of code doesn't change the result at all. – Dennis Jan 28 '19 at 20:55
  • 1
    @Dennis you need to call `map.invalidateSize()` _after_ you switch to your map view. Should you need further help, you will need to describe how and when you call your `setupMap` function. – ghybs Jan 29 '19 at 01:40
  • @ghybs I tried putting it in the map toggle function but it still shows the same bugged layout. I placed more code in the question. Thanks ! – Dennis Jan 29 '19 at 09:25
  • Looks like you invalidate the map size _before_ showing your map grid? You might also need a slight timeout to give a chance to the browser to relayout. – ghybs Jan 29 '19 at 18:50

2 Answers2

0

I had a same problem ( Uncompleted load ) and I tried it with setTimeout and it solved.

setTimeout(function () {   
    if (!myMap)
    loadmap(); /*load map function after ajax is complitly load */   
    }, 1000);

setTimeout(function () { 
     if (myMap)
     myMap.invalidateSize();
      }, 1500);

I hope it helps;

Mohsen Molaei
  • 124
  • 1
  • 4
0

I had a similar problem, it seems the tiles load, but are not positioned.

I found that loading the tiles inside the setTimeout rather than at map initialisation, even with a zero timeout, worked. e.g:

setTimeout(function () {
   tiles.addToMap(map);
},0);

This delays the rendering of the tiles long enough to ensure other script do not interfere.

Possibly the mirage script from CloudFlare is a source of the problem, but I did not have access to change CloudFlare settings for this site.

Note, in my final implementation though, I included all the map code inside the timeout so as not to have the short but noticeable delay before the tiles are rendered.