1

Similar question to this one but I don't have enough knowledge to apply it to my case.

I have a Mapbox GL JS map (based on Leaflet) to which I added a Leaflet Sidebar V1. The sidebar content is made up of html using several levels of tabs like so:

<div id="sidebar">
    <div class="tab">
        <button class="tablinks" onclick="openNation(event, 'NAT1')">Japan</button>
    </div>
    <div id="NAT1" class="tabcontent">
        <div class="row">
            <div class="col-md-auto"><div class="nav flex-column nav-pills">
                <a class="nav-link" href="#tabA1" id="listing-0" data-toggle="tab">Tokyo</a>
            </div>
            <div class="col">
                <div class="tab-content" id="v-pills-tabContent">
                    <div class="tab-pane fade" id="tabA1"><p>Description of Tokyo.</p></div>
                </div>
            </div>
        </div>
    </div>
</div>

I have a whole structure of Nations and Cities. With the sidebar open, you first click on a country, which will display the list of its cities. You click on a city in the list, and the description will display, all of that in the sidebar.

What I want to do is to display the relevant description (and mark the relevant Nation and City as active) when you click on a city on the map.

I already have some functions associated with clicking on a city like so:

map.on('click', function (e) {
    // Query all the rendered points in the view
    var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
    if (features.length) {
        var clickedPoint = features[0];
        // Fly to the point
        flyToCity(clickedPoint);
          }
        });

Initially this code was taken from a tutorial which also included this:

       // 2. Close all other popups and display popup for clicked store
        createPopUp(clickedPoint);
        // 3. Highlight listing in sidebar (and remove highlight for all other listings)
            var activeItem = document.getElementsByClassName('active');
            if (activeItem[0]) {
              activeItem[0].classList.remove('active');
            }
            // Find the index of the store.features that corresponds to the clickedPoint that fired the event listener
            var selectedFeature = clickedPoint.properties.name;

            for (var i = 0; i < cities.features.length; i++) {
              if (cities.features[i].properties.name === selectedFeature) {
                selectedFeatureIndex = i;
              }
            }
            // Select the correct list item using the found index and add the active class
            var listing = document.getElementById('listing-' + selectedFeatureIndex);
            listing.classList.add('active');
            // Shift view to selected item in sidebar
            listing.scrollIntoView(true);

I am not using the popup or the sidebar that this code is for since I've created my own Leaflet Sidebar V1, but I guess I could probably take inspiration from the code. However, I don't know enough to figure how to designate and set the leaflet sidebar content from a javascript function.

I'm attaching a screenshot for illustration purposes.

How to make map click on city display the city's description

1 Answer 1

1

The easiest route is to have your Mapbox locations trigger a click event. Since that click will be targeted at a button in the sidebar, you get any 'onClick' function and 'data-toggle' functionality from the nav menu coming along.

The code below assumes the following which is not a Mapbox default:

  1. the 'features' (aka list of cities) contains a 'nation' property;
  2. because of the 'index' variable, the order in which the 'features' appear in the code must match the order in which the city tab IDs (nav-link) are numbered in the sidebar's nav menu (starting with 0, not 1). Or you can use the same method as for the 'nation' tabs, by adding a dedicated property to each 'feature', match them with the nav-link IDs and call the same function as with nations (selectedFeature1) instead of relying on an index.

.

map.on('click', function (e) {
    var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
    if (features.length) {
        var clickedPoint = features[0];
            var selectedFeature1 = clickedPoint.properties.nation;
            var sidebar = document.getElementById('NAT-' + selectedFeature1).click();               
            var selectedFeature2 = clickedPoint.properties.name;
            for (var i = 0; i < cities.features.length; i++) {
              if (cities.features[i].properties.name === selectedFeature2) {
                selectedFeature2Index = i;
              }
            }
            var sidebar = document.getElementById('listing-' + selectedFeature2Index).click();              
    }
    });

My question had been closed whereas I think it was valid. It was about how to write a JavaScript function that simulates a click inside the Leaflet Sidebar by clicking on a choice of features included in a Mapbox map. The resulting code is listening to rendered points on the map and search for the right ID to click on in the sidebar.

I had thought this would be an easy one for people who are familiar with Mapbox's rendered location structure and some JavaScript basics. Ultimately I had to figure how JavaScript functions work from scratch to be able to write this, although I had hoped someone could give me a hand instead of closing my topic. My question and its context were sure complex, but they were perfectly clear. In the future I encourage the people who chose to comment negatively instead of helping me narrow down the issue and giving out some JS basics to be more constructive towards less skilled/first-time coders who are still able to phrase a complex question. I am therefore posting this for other such people to use.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.