Карта наведения курсора не переключает класс div на выделение с помощью JavaScript - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь, чтобы мои карты загорались всякий раз, когда я наводил указатель мыши на булавку на карте, которая соответствует карте (очень похоже на то, что у них есть на веб-сайте airbnb), но я не могу заставить ее работать .

Может быть, вы можете мне помочь. У меня есть ошибка в моем коде JS, и я пытаюсь ее отладить. В приложении RoR о ресторанах и на странице указателей я перечисляю рестораны с карточками и на большой карте, наклеенной рядом с булавками, показывающими расположение ресторанов. Есть 2 вещи, с которыми я хочу справиться в JS. Во-первых, когда я наведу курсор мыши на карточку ресторана, булавка, соответствующая ресторану, должна открыть информационное окно с названием и адресом ресторана (это работает). Второе - наоборот, когда всякий раз, когда я наводю указатель мыши на булавку на карте, карта, соответствующая этому булавке, должна менять свой фон, чтобы вы могли видеть, какой это. С этой частью у меня возникли трудности.

Это код JS, с которым я работаю:


    import 'mapbox-gl/dist/mapbox-gl.css'
    import mapboxgl from 'mapbox-gl/dist/mapbox-gl.js';


    const initMapbox = () => {
      const mapElement = document.getElementById('map');

      if (mapElement) { // only build a map if there's a div#map to inject into
        mapboxgl.accessToken = mapElement.dataset.mapboxApiKey;

        const map = new mapboxgl.Map({
          container: 'map',
          style: 'mapbox://styles/mapbox/streets-v10'
        });

        const markers = JSON.parse(mapElement.dataset.markers);
        // Here we store map markers in an array
        const mapMarkers = []

        markers.forEach((marker) => {
          const popup = new mapboxgl.Popup().setHTML(marker.infoWindow.content);

          const newMarker = new mapboxgl.Marker()
            .setLngLat([marker.lng, marker.lat])
            .setPopup(popup)
            .addTo(map);
          mapMarkers.push(newMarker)
          // We use the "getElement" funtion provided by mapbox-gl to access to the marker's HTML an set an id
          newMarker.getElement().dataset.markerId = marker.id;
          // Put a microphone on the new marker listening for a mouseenter event
          newMarker.getElement().addEventListener('mouseenter', (e) => toggleCardHighlighting(e) );
          // We put a microphone on listening for a mouseleave event
          newMarker.getElement().addEventListener('mouseleave', (e) => toggleCardHighlighting(e) );
        });

        fitMapToMarkers(map, markers);
        // We give the array of marker to a new function called "openInfoWindow"
        openInfoWindow(mapMarkers);
      }
    };

      const toggleCardHighlighting = (event) => {
        // We select the card corresponding to the marker's id
        const card = document.querySelector(`[data-restaurant-id="${event.currentTarget.dataset.markerId}"]`);
        // Then we toggle the class "highlight" to the card
        card.classList.toggle('highlight');
      }

      const fitMapToMarkers = (map, markers) => {
        const bounds = new mapboxgl.LngLatBounds();
        markers.forEach(marker => bounds.extend([ marker.lng, marker.lat ]));
        map.fitBounds(bounds, { padding: 70, maxZoom: 15 });
      };

      const openInfoWindow = (markers) => {
        const cards = document.querySelectorAll('.card');
        cards.forEach((card, index) => {
          card.addEventListener('mouseenter', () => {
            markers[index].togglePopup();
          });
          card.addEventListener('mouseleave', () => {
            markers[index].togglePopup();
          });
        });
      }


    const addressInput = document.getElementById('restaurant_address');

    if (addressInput) {
      const places = require('places.js');
      const placesAutocomplete = places({
        container: addressInput
      });
    }

    const fullAddressInput = document.getElementById('restaurant_full_address');

    if (fullAddressInput) {
      const places = require('places.js');
      const placesAutocomplete = places({
        container: fullAddressInput
      });
    }

    export { initMapbox };

Я получаю эту ошибку в консоли Chrome:


    Uncaught TypeError: Cannot read property 'classList' of null
        at toggleCardHighlighting (init_mapbox.js:64)
        at HTMLDivElement.<anonymous> (init_mapbox.js:31)

Строка 60-65 содержит эту функцию:


    const toggleCardHighlighting = (event) => {
        // We select the card corresponding to the marker's id
        const card = document.querySelector(`[data-restaurant-id="${event.currentTarget.dataset.markerId}"]`);
        // Then we toggle the class "highlight" to the card
        card.classList.toggle('highlight');
      }

Ошибка происходит в строке 65: card.classList.toggle('highlight');

HTML-код отдельной карты выглядит так:


    <div class="card index-card" style="background-image: linear-gradient(rgba(0,0,0,0.3), rgba(0,0,0,0.2)),url('https://kitt.lewagon.com/placeholder/cities/shanghai');" data-restaurant-id="532">
        <div class="card-body">
          <h2>Restaurant Example</h2>
          <p>Mediterranean cuisine. Specialising in paella, fresh fish and sangria.</p>
          <p>moderate, Ibiza, Restaurant</p>
          <a href="/restaurants/532">See more</a>
          <p>
            <a href="/tagged?tag=mediterranean">mediterranean</a>
          </p>
            <a class="card-star" rel="nofollow" data-method="put" href="/restaurants/532/vote">
              <img alt="favorite-vote" src="/assets/favorite-vote-1d5203cb3cbd136f67e5a32ece417f9707c6f6ad38946c5c9de44146f6ed4e9a.png">
    </a>    </div>
      </div>

Внутри отладчика Chrome, когда я делаю это, я получаю null, где я ожидаю, что у него будет div карты ресторана:


    document.querySelector(`[data-restaurant-id="${event.currentTarget.dataset.markerId}"]`)
    null

Эта строка дает мне undefined:


    const card = document.querySelector(`[data-restaurant-id="${event.currentTarget.dataset.markerId}"]`)
    undefined

  1. Когда я делаю только это, я получаю правильное свойство:

    [data-restaurant-id="${event.currentTarget.dataset.markerId}"]`
    "[data-restaurant-id="532"]"

  1. Но когда я делаю это, я получаю null:

    document.querySelector(`[data-restaurant- 
    id="${event.currentTarget.dataset.markerId}"]`)
    null

Так что, когда в этой части что-то идет не так, но я не могу объяснить, как это сделать document.querySelector

...