0
votes

I am working on an application where I am fetching all the users from database and then plotting them on a Mapbox map using Leaflet markers.

When a user clicks on the marker, the chat box for that particular opens up and he can chat with them.

But now I want to change this functionality slightly. I wish to have a popup using the bindPopup method in Leaflet to reveal a small information box about the user which will have the chat button, clicking which would reveal the chat box but I am failing at his somehow.

I have setup a hidden div in the body which is placeholder for the content of the popup like so:

    <div class="container-fluid">
        <div class="row">
            <div class="col-xs-6 text-left">
                <h3 id="statusHolder">Status</h3>
            </div>
            <div class="col-xs-6 text-right">
                <button id="chatWithUser" class="btn btn-primary" href="">Chat</button>
            </div>
        </div>
    </div>

Now this is the JS code which puts the markers in place and manipulates the content of the popup. It has marker on click event defined as well as the button on click too. Marker on click is working fine. Button on click doesn't. Nothing happens. No console error. In fact I cannot even log anything in the console via it.

$.getJSON('/users', function(response){

    $.each(response, function(i, user){

        // Parsing lat, lng values
        var lat = parseFloat(user.farmer_profile.lat);
        var lng = parseFloat(user.farmer_profile.lng);

        // Setting marker color based on status
        switch(user.status){
            case 'Available':
            var color = '#659265';
            break;
            case 'Busy':
            var color = '#C46A69';
            break;
            case 'Idle':
            var color = '#C79121';
            break;
        }

        // Setting icon of marker to differentiate between 
        // current user and everyone else
        var icon;
        var size;

        if(user.id == currentUser.id){
            icon = 'star';
            size = 'large';
        }else{
            icon = 'pitch'
        }

        // Plotting marker on the map for the farmer
        var marker = L.marker([lat, lng], {
            icon: L.mapbox.marker.icon({
                'marker-size': size,
                'marker-symbol': icon,
                'marker-color': color
            }),
        }).addTo(map);

        // Don't bind the existing user with the chat function.
        if(user.id == currentUser.id){

            return true;
        }

        // Binding the marker on click event to bring up the chat
        // This was working fine
        /*marker.on('click', function(){
            var chatboxId = 'chat-' + currentUser.id + '-' + user.id;
            chatboxManager.addBox(chatboxId, {
                first_name: user.first_name,
                last_name: user.last_name,
            });

            $('#' + chatboxId).chatbox({
                messageSent: function(id, user, message){
                    this.boxManager.addMsg('Me', message);

                    splittedId = id.split('-');

                    $.ajax({
                        url: '/messages',
                        method: 'post',
                        type: 'json',
                        data: {
                            receiver_id: splittedId[2],
                            body: message
                        }
                    });
                }
            });
        });*/

        $('span#firstNameHolder').text(user.first_name);
        $('span#lastNameHolder').text(user.last_name);

        $('b#farmNameHolder').text(user.farmer_profile.farm_name);

        $('b#latHolder').text(user.farmer_profile.lat);
        $('b#lngHolder').text(user.farmer_profile.lat);

        $('h3#statusHolder').text(user.status);

        // This is not yeilding any results.
        // Not event the console.log('hello');
        $('#chatWithUser').on('click', function(e){
            console.log('hello');
            var chatboxId = 'chat-' + currentUser.id + '-' + user.id;
            chatboxManager.addBox(chatboxId, {
                first_name: user.first_name,
                last_name: user.last_name,
            });

            $('#' + chatboxId).chatbox({
                messageSent: function(id, user, message){
                    this.boxManager.addMsg('Me', message);

                    splittedId = id.split('-');

                    $.ajax({
                        url: '/messages',
                        method: 'post',
                        type: 'json',
                        data: {
                            receiver_id: splittedId[2],
                            body: message
                        }
                    });
                }
            });
        });

        var popupContent = $('#popupContent').html();
        marker.bindPopup(popupContent);
    });
});

Can anyone point out what I am missing?

1
Did you try to use a delegated event? $(document).on('click', '#chatWithUser', function(e){ /*...*/ });kosmos
I am afraid I am not sure how this works. I shall look into delegated events first. Thank you for your quick reply anyway.Rohan
You are welcome. If you know the deprecated .live() method, this is the new way to deletage events across the DOM. Check docs 👍kosmos
I tried your code $(document).on('click', '#chatWithUser', function(e){ /*...*/ });. It works but unfortunately not as I needed. It opens all the chat boxes at once. Can you help me with a similar solution but to target only the chat button that is clicked? :)Rohan
Maybe it happens because you are using the same ID to all chat boxes, remember that an ID must be an unique identifier. If it is the case, you should think in change it to a class. I'll post an answer to explain it.kosmos

1 Answers

0
votes

Okay so I finally figured out what went wrong. There were a couple of things actually.

First, all the chat buttons had the same id chatWithUser and hence were clashing.

So I went ahead and edited the code a little:

var popupContent = $('div#popupContent').clone();

popupContent.find('span#firstNameHolder').text(user.first_name);
popupContent.find('span#lastNameHolder').text(user.last_name);

popupContent.find('b#farmNameHolder').text(user.farmer_profile.farm_name);

popupContent.find('b#latHolder').text(user.farmer_profile.lat);
popupContent.find('b#lngHolder').text(user.farmer_profile.lat);

popupContent.find('h3#statusHolder').text(user.status);

popupContent.find('#chatWithUser').attr('id', 'chatWithUser' + i);

$(document).on('click', '#chatWithUser' + i, function(e){
    console.log('hello');
    var chatboxId = 'chat-' + currentUser.id + '-' + user.id;
    chatboxManager.addBox(chatboxId, {
        first_name: user.first_name,
        last_name: user.last_name,
    });

    $('#' + chatboxId).chatbox({
        messageSent: function(id, user, message){
            this.boxManager.addMsg('Me', message);

            splittedId = id.split('-');

            $.ajax({
                url: '/messages',
                method: 'post',
                type: 'json',
                data: {
                    receiver_id: splittedId[2],
                    body: message
                }
            });
        }
    });
});

console.log(popupContent.html());

marker.bindPopup(popupContent.html());

Instead of taking the original div, I cloned it each time in the loop and gave the chat button and id of '#chatWithUser' + i which solved the clashing problem.

But even at this point, the on click event was not working. So I took the advice of @kmsdev and used the delegated event like so:

$(document).on('click', '#chatWithUser' + i, function(e){
// my code here
});

Although I am still not perfectly clear why this works and why not a simple $(ele).on('click', callback); but this solution worked for me.