javascripthtmlrazorleafletleaflet-routing-machine

Leaflet Routing Machine - Route Control: how to add a click listener to each instructions in the itinerary table?


currently, the default action when clicking part of a route is that it will zoom into that coordinate on the map.

im currently trying to add a text to speech that will say out the instructions for that particular part.

but how do i modify the click listener that is already built-in L.Routing.control?

the code below belongs to me:

var routeControl = L.Routing.control({
                waypoints: [
                    L.latLng(1.2734916210174561, 103.80210876464844),
                    L.latLng(1.314766, 103.765229)
                ],
                routeWhileDragging: true,
                geocoder: L.Control.Geocoder.nominatim({ geocodingQueryParams: { "countrycodes": 'SG' } })

            }).addTo(map);

            routeControl.on('routeselected', function (e) {

                var coord = e.route.instructions;

                if ('speechSynthesis' in window) {

                    for (let i = 0; i < coord.length; i++)
                    {
                        //speak(coord[i].text);
                    }
                }
                else {
                      alert("your broswer does not support text to speech");
                }


            });

whereas this code below belongs to the original author which is loaded automatically when a route is found: https://github.com/perliedman/leaflet-routing-machine/blob/master/src/itinerary.js

_createItineraryContainer: function(r) {
            var container = this._itineraryBuilder.createContainer(),
                steps = this._itineraryBuilder.createStepsContainer(),
                i,
                instr,
                step,
                distance,
                text,
                icon;

            container.appendChild(steps);

            for (i = 0; i < r.instructions.length; i++) {
                instr = r.instructions[i];
                text = this._formatter.formatInstruction(instr, i);
                distance = this._formatter.formatDistance(instr.distance);
                icon = this._formatter.getIconName(instr, i);
                step = this._itineraryBuilder.createStep(text, distance, icon, steps);

                if(instr.index) {
                    this._addRowListeners(step, r.coordinates[instr.index]);
                }
            }

            return container;
        },

        _addRowListeners: function(row, coordinate) {
            L.DomEvent.addListener(row, 'mouseover', function() {
                this._marker = L.circleMarker(coordinate,
                    this.options.pointMarkerStyle).addTo(this._map);
            }, this);
            L.DomEvent.addListener(row, 'mouseout', function() {
                if (this._marker) {
                    this._map.removeLayer(this._marker);
                    delete this._marker;
                }
            }, this);
            L.DomEvent.addListener(row, 'click', function(e) {
                this._map.panTo(coordinate);
                L.DomEvent.stopPropagation(e);
            }, this);
        },

so i'm trying to figure how do i access this to add my speech function

L.DomEvent.addListener(row, 'click', function(e) {
                this._map.panTo(coordinate);
                L.DomEvent.stopPropagation(e);
            }, this);

when it's already been initialized


Solution

  • In the code you have pasted, you can see that Leaflet Routing Machine uses something called a ItineraryBuilder, which is responsible for creating the DOM elements for the itinerary.

    You can provide your own ItineraryBuilder, overriding the default builder, when creating the control. With your own custom implementation, you should be able to override the createStep method to make it add whatever listener you need.

    One possible issue is that I see that the default click event handler calls stopPropagation on the event, which probably means that a listener you attach higher up in the DOM hierarchy will not see the click event. If this is the case, you would need a way to prevent _addRowListeners from being called, which to my memory currently does not exist.