Отключить всплывающее окно закрытия события при нажатии на ссылку в всплывающем - PullRequest
0 голосов
/ 14 сентября 2018

Я использую Mapbox GL JS в интерфейсе React и использую отдельный компонент для отображения всплывающих окон Mapbox примерно так (код сокращен в качестве примера):

import React from 'react';
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = CONFIG.MAPBOX.ACCESS_TOKEN;

// Pass router context to components that are rendered tith React.render()
function withContext(WrappedComponent, context){

    class ContextProvider extends React.Component {
        getChildContext() {
            return context;
        }
        render() {
            return <WrappedComponent {...this.props} />
        }
    }

    ContextProvider.childContextTypes = {};
    Object.keys(context).forEach(key => {
        ContextProvider.childContextTypes[key] = PropTypes.any.isRequired;
    });

    return ContextProvider;
}

class InteractiveMap extends React.Component {

    constructor(props) {
        this.map;
        this.mapSource;
        this.popup;
        this.popupContainer;
        this.hasOpenPopup = false;
    }

    // This make sure you have router in your this.context
    static contextTypes = {
        router: PropTypes.object.isRequired
    }

    addCustomPopup(feature) {
        if (feature) {
            // Pass router context
            const MapPopupWithContext = withContext(MapPopup, this.context);
            ReactDOM.render(
                <Provider store={STORE}>
                    <MapPopupWithContext
                        feature={feature}
                        extended={true}
                        onClick={(type, item, coordinates) => this.handlePopUpLink(type, item, coordinates)}
                    />
                </Provider>,
                this.popupContainer,
                (() => {
                    this.hasOpenPopup = true;
                    ReactDOM.unmountComponentAtNode(this.tooltipContainer);
                })
            );
        }
    }

    handlePopUpLink(item) {
        // open other react component
        this.hasOpenPopup = false;
    }

    this.map = new mapboxgl.Map({
        container: this.mapContainer
    });

    this.map.on('load', () => {
        this.map.addSource('features', {
            type   : 'geojson',
            data   : this.mapSource
        });
    });

    // Add Popup containers with z-index
    this.popupContainer = document.createElement('div');
    this.popupContainer.classList.add('b-map-popup', 'is-popup');

    // Add Popup
    this.popup = new mapboxgl.Popup({
            closeButton : false,
            closeOnClick: false,
            anchor      : 'bottom'
        })
        .setDOMContent(this.popupContainer)
        .setLngLat([0,0])
        .addTo(this.map);

    this.popup.on('close', (e) => {
        // always fires on popup link click
        console.log('popup close');
    });

    // Add layer
    this.map.addLayer({
        id: layerID,
        type: 'symbol',
        source: 'features',
        layout: {
            'icon-image'           : 'layer',
            'icon-size'            : 0.5,
            'icon-allow-overlap'   : true,
            'icon-ignore-placement': true,
            'text-allow-overlap'   : true
        }
    });

    // Open clicked feature in popup
    this.map.on('click', (e) => {
        const feature = this.map.queryRenderedFeatures(e.point, {
            radius: 100,
            layers: 'layer'
        });

        if (!feature) {
            // If on the map, remove the current popup
            this.popup.remove();
            this.hasOpenPopup = false;
        } else {
            if (feature.geometry.type === 'Point') {
                e.lngLat = feature.geometry.coordinates;
            }

            this.popup.setLngLat(e.lngLat);
            this.popup.addTo(this.map);
            this.addCustomPopup(feature);
        }
    });

    render() {
        return (
            <div className={'b-map'} ref={el => this.mapContainer = el} />
        );
    }
}

class MapPopup extends React.Component {

    onClick(event, item) {
        const { onClick } = this.props;

        // Disable on popup close here

        onClick(item);
    }

    render() {
        const { feature } = this.props;

        // Content
        popupContent = (
            <div className="b-map-popup__content">
                <div className='b-map-popup__content-wrap'>
                    <h1 className='b-map-popup__title'>{feature.title}</h1>
                    <a className="b-map-popup__button" onClick={(e) => this.onClick(e, clickItem)}>{'Lees meer'}</a>
                </div>
            </div>
        );


        return (
            <div className="b-map-popup__wrapper">
                {popupContent}
                <span className="b-map-popup__arrow"></span>
            </div>
        );
    }
}

MapPopup.propTypes = {
    feature        : PropTypes.object.isRequired,
    onClick        : PropTypes.func
}

Во всплывающем окне есть несколько ссылок, которые взаимодействуют с другими компонентами React. Однако нажатие на эти ссылки всегда вызывает событие Popup close.

Как я могу получить контроль, когда всплывающее окно должно закрываться, а когда нет?

Я нашел этот старый документ , который также требует jQuery, но основное отличие состоит в том, что я использую setdomcontent для заполнения всплывающего окна содержимым HTML.

Большое спасибо за любые указатели!

РЕДАКТИРОВАТЬ 1

На самом деле я обнаружил, что событие close вызывается не самой ссылкой, а событием map.flyTo(), вызываемым ссылкой.

Таким образом, мой вопрос должен заключаться в следующем: как предотвратить событие закрытия всплывающего окна, инициируемое flyTo (которое вызывает несколько событий на карте, таких как: перемещение, масштабирование, масштабирование, масштабирование, изменение высоты тона, высота тона, питченд)?

...