Слушатели событий карты

Open on CodeSandbox

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>

    <script crossorigin src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

    <!-- To make the map appear, you must add your apikey -->
    <script src="https://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import type {
          MapEventUpdateHandler,
          MapEventResizeHandler,
          DomEventHandler,
          BehaviorMapEventHandler
      } from '@yandex/ymaps3-types';
      import {LOCATION, BEHAVIOR, EventListener, InfoMessage} from './common';

      window.map = null;

      main();
      async function main() {
          // Waiting for all api elements to be loaded
          await ymaps3.ready;
          const {YMap, YMapDefaultSchemeLayer, YMapListener, YMapControls, YMapControl} = ymaps3;
          // Initialize the map
          map = new YMap(
              // Pass the link to the HTMLElement of the container
              document.getElementById('app'),
              // Pass the map initialization parameters
              {location: LOCATION, showScaleInCopyrights: true, behaviors: BEHAVIOR},
              // Add a map scheme layer
              [new YMapDefaultSchemeLayer({})]
          );

          // Status of map events
          const mapEvents = {
              update: false,
              resize: false
          };

          // Status of dom events
          const domEvents = {
              click: false,
              fastClick: false,
              dblClick: false,
              rightClick: false,
              rightDblClick: false,
              mouseMove: false,
              mouseEnter: false,
              mouseLeave: false,
              mouseDown: false
          };

          // Status of behavior events
          const behaviorEvents = {
              scrollZoom: false,
              drag: false,
              mouseRotate: false,
              mouseTilt: false
          };

          // Create an EventListener control to display the status of map events
          const mapEventsControl = new EventListener({
              title: 'Map Events',
              events: {...mapEvents}
          });

          // Create an EventListener control to display the status of dom events
          const domEventsControl = new EventListener({
              title: 'Dom Events',
              events: {...domEvents}
          });

          // Create an EventListener control to display the status of behavior events
          const behaviorEventsControl = new EventListener({
              title: 'Behavior Events',
              events: {...behaviorEvents}
          });

          /* Create and add a shared container for controls to the map.
          Using YMapControls you can change the position of the control */
          const topLeftControls = new YMapControls({position: 'top left', orientation: 'horizontal'});
          map.addChild(topLeftControls);

          // Add controls to the map
          topLeftControls
              .addChild(new YMapControl().addChild(domEventsControl))
              .addChild(new YMapControl().addChild(mapEventsControl).addChild(behaviorEventsControl));

          // Handler function for changing the status of the onUpdate event
          const updateHandler: MapEventUpdateHandler = (object) => {
              console.log('Update object: ', object);

              object.mapInAction ? (mapEvents.update = true) : (mapEvents.update = false);
              mapEventsControl.update({events: {...mapEvents}});
          };

          // Function that creates a handler function to change the status of the onResize event
          const createResizeHandler = (): MapEventResizeHandler => {
              const disableResizeEvent = _.debounce(() => {
                  mapEvents.resize = false;
                  mapEventsControl.update({events: {...mapEvents}});
              }, 250);

              return function (object) {
                  console.log('Resize object: ', object);

                  mapEvents.resize = true;
                  mapEventsControl.update({events: {...mapEvents}});

                  disableResizeEvent();
              };
          };

          // Function that creates a handler function to change the status of dom events
          const createDomEventHandler = (eventType: keyof typeof domEvents): DomEventHandler => {
              const disableEvent = _.debounce(() => {
                  domEvents[eventType] = false;
                  domEventsControl.update({
                      events: {
                          ...domEvents
                      }
                  });
              }, 250);

              return function (object, event) {
                  console.log(`${eventType} object: `, object, `\n${eventType} event: `, event);

                  domEvents[eventType] = true;
                  domEventsControl.update({
                      events: {
                          ...domEvents
                      }
                  });

                  disableEvent();
              };
          };

          // Function that creates a handler function to change the status of behavior event
          const createBehaviorEventHandler = (isStart: boolean): BehaviorMapEventHandler => {
              return function (object) {
                  if (object.type === 'dblClick') return;

                  if (isStart) {
                      console.log('actionStart object: ', object);
                  } else {
                      console.log('actionEnd object: ', object);
                  }

                  behaviorEvents[object.type] = isStart;
                  behaviorEventsControl.update({events: {...behaviorEvents}});
              };
          };

          /* Add a listener to the map and pass the handlers functions for the events you want to process
          These are just some of the events, you can see them all in the documentation */
          map.addChild(
              new YMapListener({
                  onUpdate: updateHandler,
                  onResize: createResizeHandler(),

                  onClick: createDomEventHandler('click'),
                  onFastClick: createDomEventHandler('fastClick'),
                  onDblClick: createDomEventHandler('dblClick'),
                  onContextMenu: createDomEventHandler('rightClick'),
                  onRightDblClick: createDomEventHandler('rightDblClick'),
                  onMouseMove: createDomEventHandler('mouseMove'),
                  onMouseEnter: createDomEventHandler('mouseEnter'),
                  onMouseLeave: createDomEventHandler('mouseLeave'),
                  onMouseDown: createDomEventHandler('mouseDown'),

                  onActionStart: createBehaviorEventHandler(true),
                  onActionEnd: createBehaviorEventHandler(false)
              })
          );

          /* Create and add a shared container for controls to the map.
          Using YMapControls you can change the position of the control */
          const topRightControls1 = new YMapControls({position: 'top right'});
          map.addChild(topRightControls1);

          // Add a custom information message control to the map
          topRightControls1.addChild(
              new InfoMessage({text: 'Open the console to see the parameters of the executed event.'})
          );
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.production.min.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>

    <script crossorigin src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

    <!-- To make the map appear, you must add your apikey -->
    <script src="https://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="react, typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
      import type {
          MapEventUpdateHandler,
          MapEventResizeHandler,
          DomEventHandler,
          BehaviorMapEventHandler
      } from '@yandex/ymaps3-types';
      import {LOCATION, BEHAVIOR, EventListener, InfoMessage} from './common';

      window.map = null;

      main();
      async function main() {
          // For each object in the JS API, there is a React counterpart
          // To use the React version of the API, include the module @yandex/ymaps3-reactify
          const [ymaps3React] = await Promise.all([ymaps3.import('@yandex/ymaps3-reactify'), ymaps3.ready]);
          const reactify = ymaps3React.reactify.bindTo(React, ReactDOM);
          const {YMap, YMapDefaultSchemeLayer, YMapListener, YMapControls, YMapControl} = reactify.module(ymaps3);

          // Using ymaps3-rectify, we turn a custom InfoMessage and EventListener into a React component
          const {EventListener: EventListenerR} = reactify.module({EventListener});
          const {InfoMessage: InfoMessageR} = reactify.module({InfoMessage});

          const {useState, useCallback, useMemo} = React;

          function App() {
              // Status of map events
              const [mapEvents, setMapEvents] = useState({
                  update: false,
                  resize: false
              });

              // Status of dom events
              const [domEvents, setDomEvents] = useState({
                  click: false,
                  fastClick: false,
                  dblClick: false,
                  rightClick: false,
                  rightDblClick: false,
                  mouseMove: false,
                  mouseEnter: false,
                  mouseLeave: false,
                  mouseDown: false
              });

              // Status of behavior events
              const [behaviorEvents, setBehaviorEvents] = useState({
                  scrollZoom: false,
                  drag: false,
                  mouseRotate: false,
                  mouseTilt: false
              });

              // Handler function for changing the status of the onUpdate event
              const updateHandler: MapEventUpdateHandler = useCallback((object) => {
                  console.log('Update object: ', object);

                  object.mapInAction ? (mapEvents.update = true) : (mapEvents.update = false);
                  setMapEvents({...mapEvents});
              }, []);

              // Function that creates a handler function to change the status of the onResize event
              const createResizeHandler = useCallback((): MapEventResizeHandler => {
                  const disableResizeEvent = _.debounce(() => {
                      mapEvents.resize = false;
                      setMapEvents({...mapEvents});
                  }, 250);

                  return function (object) {
                      console.log('Resize object: ', object);

                      mapEvents.resize = true;
                      setMapEvents({...mapEvents});

                      disableResizeEvent();
                  };
              }, []);

              // Function that creates a handler function to change the status of dom events
              const createDomEventHandler = useCallback((eventType: keyof typeof domEvents): DomEventHandler => {
                  const disableEvent = _.debounce(() => {
                      domEvents[eventType] = false;
                      setDomEvents({...domEvents});
                  }, 250);

                  return function (object, event) {
                      console.log(`${eventType} object: `, object, `\n${eventType} event: `, event);

                      domEvents[eventType] = true;
                      setDomEvents({...domEvents});

                      disableEvent();
                  };
              }, []);

              // Function that creates a handler function to change the status of behavior event
              const createBehaviorEventHandler = useCallback((isStart: boolean): BehaviorMapEventHandler => {
                  return function (object) {
                      if (object.type === 'dblClick') return;

                      if (isStart) {
                          console.log('actionStart object: ', object);
                      } else {
                          console.log('actionEnd object: ', object);
                      }

                      behaviorEvents[object.type] = isStart;
                      setBehaviorEvents({...behaviorEvents});
                  };
              }, []);

              return (
                  // Initialize the map and pass initialization parameters
                  <YMap location={LOCATION} showScaleInCopyrights={true} behaviors={BEHAVIOR} ref={(x) => (map = x)}>
                      {/* Add a map scheme layer */}
                      <YMapDefaultSchemeLayer />

                      {/* Add a shared container for controls to the map.
                      Using YMapControls you can change the position of the control */}
                      <YMapControls position="top left" orientation="horizontal">
                          <YMapControl>
                              {/* Add an EventListener control to the map to display the status of dom events */}
                              <EventListenerR title="Dom Events" events={domEvents} />
                          </YMapControl>
                          <YMapControl>
                              {/* Add an EventListener control to the map to display the status of map events */}
                              <EventListenerR title="Map Events" events={mapEvents} />
                              {/* Add an EventListener control to the map to display the status of behavior events */}
                              <EventListenerR title="Behavior Events" events={behaviorEvents} />
                          </YMapControl>
                      </YMapControls>

                      {/* Add a listener to the map and pass the handlers functions for the events you want to process
                      These are just some of the events, you can see them all in the documentation */}
                      <YMapListener
                          onUpdate={updateHandler}
                          onResize={useMemo(() => createResizeHandler(), [])}
                          onClick={useMemo(() => createDomEventHandler('click'), [])}
                          onFastClick={useMemo(() => createDomEventHandler('fastClick'), [])}
                          onDblClick={useMemo(() => createDomEventHandler('dblClick'), [])}
                          onContextMenu={useMemo(() => createDomEventHandler('rightClick'), [])}
                          onRightDblClick={useMemo(() => createDomEventHandler('rightDblClick'), [])}
                          onMouseMove={useMemo(() => createDomEventHandler('mouseMove'), [])}
                          onMouseEnter={useMemo(() => createDomEventHandler('mouseEnter'), [])}
                          onMouseLeave={useMemo(() => createDomEventHandler('mouseLeave'), [])}
                          onMouseDown={useMemo(() => createDomEventHandler('mouseDown'), [])}
                          onActionStart={useMemo(() => createBehaviorEventHandler(true), [])}
                          onActionEnd={useMemo(() => createBehaviorEventHandler(false), [])}
                      />

                      <YMapControls position="top right">
                          {/* Add a custom information message control to the map */}
                          <InfoMessageR text="Open the console to see the parameters of the executed event." />
                      </YMapControls>
                  </YMap>
              );
          }

          ReactDOM.render(
              <React.StrictMode>
                  <App />
              </React.StrictMode>,
              document.getElementById('app')
          );
      }
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
    <script crossorigin src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
    <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>

    <script crossorigin src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

    <!-- To make the map appear, you must add your apikey -->
    <script src="https://api-maps.yandex.ru/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

    <script
      data-plugins="transform-modules-umd"
      data-presets="typescript"
      type="text/babel"
      src="./common.ts"
    ></script>
    <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
      import {LOCATION, BEHAVIOR, EventListener, InfoMessage} from './common';

      window.map = null;

      async function main() {
        // For each object in the JS API, there is a Vue counterpart
        // To use the Vue version of the API, include the module @yandex/ymaps3-vuefy
        const [ymaps3Vue] = await Promise.all([ymaps3.import('@yandex/ymaps3-vuefy'), ymaps3.ready]);
        const vuefy = ymaps3Vue.vuefy.bindTo(Vue);
        const {YMap, YMapDefaultSchemeLayer, YMapListener, YMapControls, YMapControl} = vuefy.module(ymaps3);

        // Using ymaps3-vuefy, we turn a custom InfoMessage and EventListener into a Vue component
        const {EventListener: EventListenerV} = vuefy.module(
          {EventListener},
          {
            EventListener: {title: String, events: Object}
          }
        );
        const {InfoMessage: InfoMessageV} = vuefy.module({InfoMessage});

        const mapEvents = Vue.ref({
          update: false,
          resize: false
        });

        const updateHandler = (object) => {
          console.log('Update object: ', object);
          mapEvents.value.update = !!object.mapInAction;
          mapEvents.value = {...mapEvents.value};
        };

        const domEvents = Vue.ref({
          click: false,
          fastClick: false,
          dblClick: false,
          rightClick: false,
          rightDblClick: false,
          mouseMove: false,
          mouseEnter: false,
          mouseLeave: false,
          mouseDown: false
        });

        const behaviorEvents = Vue.ref({
          scrollZoom: false,
          drag: false,
          mouseRotate: false,
          mouseTilt: false
        });

        const createResizeHandler = () => {
          const disableResizeEvent = _.debounce(() => {
            mapEvents.value.resize = false;
            mapEvents.value = {...mapEvents.value};
          }, 250);

          return function (object) {
            console.log('Resize object: ', object);
            mapEvents.value.resize = true;
            mapEvents.value = {...mapEvents.value};
            disableResizeEvent();
          };
        };

        const createDomEventHandler = (eventType) => {
          const disableEvent = _.debounce(() => {
            domEvents.value[eventType] = false;
            domEvents.value = {...domEvents.value};
          }, 250);

          return function (object, event) {
            console.log(`${eventType} object: `, object, `\n${eventType} event: `, event);
            domEvents.value[eventType] = true;
            domEvents.value = {...domEvents.value};
            disableEvent();
          };
        };

        const createBehaviorEventHandler = (isStart) => {
          return function (object) {
            if (object.type === 'dblClick') return;
            console.log(`${isStart ? 'actionStart' : 'actionEnd'} object: `, object);
            behaviorEvents.value[object.type] = isStart;
            behaviorEvents.value = {...behaviorEvents.value};
          };
        };
        const app = Vue.createApp({
          components: {
            YMap,
            YMapDefaultSchemeLayer,
            YMapListener,
            YMapControls,
            YMapControl,
            EventListenerV,
            InfoMessageV
          },
          setup() {
            const refMap = (ref) => {
              window.map = ref?.entity;
            };
            return {
              LOCATION,
              BEHAVIOR,
              refMap,
              domEvents,
              mapEvents,
              behaviorEvents,
              updateHandler,
              createResizeHandler,
              createDomEventHandler,
              createBehaviorEventHandler
            };
          },
          template: `
          <!-- Initialize the map and pass initialization parameters -->
          <YMap :location="LOCATION" :showScaleInCopyrights="true" :behaviors="BEHAVIOR" :ref="refMap">
            <!-- Add a map scheme layer -->
            <YMapDefaultSchemeLayer/>

            <!-- Add a shared container for controls to the map.
            Using YMapControls you can change the position of the control -->
            <YMapControls position="top left" orientation="horizontal">
              <YMapControl>
                <!-- Add an EventListener control to the map to display the status of dom events -->
                <EventListenerV title="Dom Events" :events="domEvents"/>
              </YMapControl>
              <YMapControl>
                <!-- Add an EventListener control to the map to display the status of map events -->
                <EventListenerV title="Map Events" :events="mapEvents"/>
                <!-- Add an EventListener control to the map to display the status of behavior events -->
                <EventListenerV title="Behavior Events" :events="behaviorEvents"/>
              </YMapControl>
            </YMapControls>

            <!-- Add a listener to the map and pass the handlers functions for the events you want to process
            These are just some of the events, you can see them all in the documentation -->
            <YMapListener
                @update="updateHandler"
                @resize="(o) => createResizeHandler()(o)"
                @click="(o, e) => createDomEventHandler('click')(o, e)"
                @fastClick="(o, e) => createDomEventHandler('fastClick')(o, e)"
                @dblClick="(o, e) => createDomEventHandler('dblClick')(o, e)"
                @contextMenu="(o, e) => createDomEventHandler('rightClick')(o, e)"
                @rightDblClick="(o, e) => createDomEventHandler('rightDblClick')(o, e)"
                @mouseMove="(o, e) => createDomEventHandler('mouseMove')(o, e)"
                @mouseEnter="(o, e) => createDomEventHandler('mouseEnter')(o, e)"
                @mouseLeave="(o, e) => createDomEventHandler('mouseLeave')(o, e)"
                @mouseDown="(o, e) => createDomEventHandler('mouseDown')(o, e)"
                @actionStart="o => createBehaviorEventHandler(true)(o)"
                @actionEnd="o => createBehaviorEventHandler(false)(o)"
            />

            <YMapControls position="top right">
              <!-- Add a custom information message control to the map -->
              <InfoMessageV text="Open the console to see the parameters of the executed event."/>
            </YMapControls>
          </YMap>
        `
        });
        app.mount('#app');
      }

      main();
    </script>

    <!-- prettier-ignore -->
    <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
    <link rel="stylesheet" href="./common.css" />
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
.events {
  width: 180px;
  padding: 10px 0;

  display: flex;
  align-items: center;
  flex-direction: column;
  gap: 7px 0;
}

.events:nth-child(2)::before {
  content: '';
  display: block;
  border-top: 1px solid #c0c0c1;
  padding-top: 7px;
  width: 75%;
}

.events__title {
  font-size: 20px;
  font-weight: bold;
}

.events__list {
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;

  display: flex;
  flex-direction: column;
}

.events__item {
  width: 100%;

  padding: 5px 0;
  border-top: 1px solid #000;

  font-size: 18px;
  text-align: center;
}

.events__item:last-child {
  border-bottom: 1px solid #000;
}

.events__item_active {
  background-color: rgba(0, 122, 252, 0.7);
}

.infoWindow {
  width: 300px;
  padding: 15px;
  padding-left: 50px;

  position: relative;

  border-radius: 15px;
  background-color: rgba(255, 255, 255, 0.9);
  font-size: 16px;
}

.infoWindow__icon {
  width: 30px;
  height: 30px;

  position: absolute;
  top: 50%;
  left: 10px;
  transform: translateY(-50%);
}
import type lodash from 'lodash';
import type {YMapLocationRequest, BehaviorType} from '@yandex/ymaps3-types';
declare global {
  const _: typeof lodash;
}

export const LOCATION: YMapLocationRequest = {
  center: [37.623082, 55.75254], // starting position [lng, lat]
  zoom: 9 // starting zoom
};

// An array of enabled map behaviors
export const BEHAVIOR: BehaviorType[] = ['drag', 'scrollZoom', 'dblClick', 'mouseRotate', 'mouseTilt'];

/* Initialize a custom EventListener control
Assign a value to it after loading the map api */
export let EventListener = null;

type mapEventsType = {
  title: string;
  events: {
    update: boolean;
    resize: boolean;
  };
};

type domEventsType = {
  title: string;
  events: {
    click: boolean;
    fastClick: boolean;
    dblClick: boolean;
    rightClick: boolean;
    rightDblClick: boolean;
    mouseMove: boolean;
    mouseEnter: boolean;
    mouseLeave: boolean;
    mouseDown: boolean;
  };
};

type behaviorEventsType = {
  title: string;
  events: {
    scrollZoom: boolean;
    drag: boolean;
    mouseRotate: boolean;
    mouseTilt: boolean;
  };
};

type EventListenerProps = mapEventsType | domEventsType | behaviorEventsType;

/* Initialize a custom information message control
Assign a value to it after loading the map api */
export let InfoMessage = null;

interface InfoMessageProps {
  text: string;
}

// Wait for the api to load to access the entity system (YMapComplexEntity)
ymaps3.ready.then(() => {
  class EventListenerClass extends ymaps3.YMapComplexEntity<EventListenerProps> {
    private _element: HTMLDivElement;
    private _detachDom: () => void;

    // Method for create a DOM control element
    _createElement() {
      const {title, events} = this._props;

      // Create a root element
      const rootElement = document.createElement('div');
      rootElement.className = 'events';

      // Create an events title element
      const eventsTitle = document.createElement('div');
      eventsTitle.textContent = title;
      eventsTitle.className = 'events__title';
      rootElement.appendChild(eventsTitle);

      // Create an events list element
      const eventsList = document.createElement('ul');
      eventsList.className = 'events__list';
      rootElement.appendChild(eventsList);

      // Iterate through the events and create list items
      for (let event in events) {
        const eventElement = document.createElement('li');
        eventElement.className = 'events__item';
        eventElement.textContent = event;
        eventElement.id = event;

        eventsList.appendChild(eventElement);
      }

      return rootElement;
    }

    // Method that is used when updating the parameters of control
    _onUpdate() {
      const {events} = this._props;

      for (let event in events) {
        const eventElement = document.getElementById(event);
        if (!eventElement) return;

        if (events[event]) {
          eventElement.classList.add('events__item_active');
        } else {
          eventElement.classList.remove('events__item_active');
        }
      }
    }

    // Method for attaching the control to the map
    _onAttach() {
      this._element = this._createElement();
      this._detachDom = ymaps3.useDomContext(this, this._element, this._element);
    }

    // Method for detaching control from the map
    _onDetach() {
      this._detachDom();
      this._detachDom = null;
      this._element = null;
    }
  }
  EventListener = EventListenerClass;

  class InfoMessageClass extends ymaps3.YMapComplexEntity<InfoMessageProps> {
    private _element!: HTMLDivElement;
    private _detachDom!: () => void;

    // Method for create a DOM control element
    _createElement(props: InfoMessageProps) {
      // Create a root element
      const infoWindow = document.createElement('div');
      infoWindow.className = 'infoWindow';
      infoWindow.textContent = props.text;

      // Create an icon element
      const infoIcon = document.createElement('img');
      infoIcon.src = '../info-icon.svg';
      infoIcon.className = 'infoWindow__icon';
      infoWindow.appendChild(infoIcon);

      return infoWindow;
    }

    // Method for attaching the control to the map
    _onAttach() {
      this._element = this._createElement(this._props);
      this._detachDom = ymaps3.useDomContext(this, this._element, this._element);
    }

    // Method for detaching control from the map
    _onDetach() {
      this._detachDom();
      this._detachDom = undefined;
      this._element = undefined;
    }
  }
  InfoMessage = InfoMessageClass;
});