← back to Interiordesignershowroom

public/js/hotspots.js

47 lines

// Shoppable room-setting hotspots. Tapping a dot opens its inline product card;
// the card flips above/below and clamps left/right so it never leaves the image.
// Outside-click and Esc close it. Keyboard: dots are real <button>s, Enter toggles.
(function () {
  document.querySelectorAll('.room-scene-wrap.has-spots').forEach(function (wrap) {
    var layer = wrap.querySelector('.hotspot-layer');
    if (!layer) return;
    var open = null;

    function close() {
      if (!open) return;
      open.card.hidden = true;
      open.btn.setAttribute('aria-expanded', 'false');
      open = null;
    }
    function openCard(btn) {
      close();
      var card = wrap.querySelector('#' + btn.getAttribute('data-card'));
      if (!card) return;
      // vertical flip: if the dot is high in the image, drop the card below it
      var topPct = parseFloat(card.style.top) || 50;
      card.classList.toggle('below', topPct < 42);
      // horizontal clamp: keep the card edge inside the figure
      var leftPct = parseFloat(card.style.left) || 50;
      card.classList.toggle('edge-left', leftPct < 22);
      card.classList.toggle('edge-right', leftPct > 78);
      card.hidden = false;
      btn.setAttribute('aria-expanded', 'true');
      open = { btn: btn, card: card };
    }

    layer.addEventListener('click', function (e) {
      var btn = e.target.closest('.hotspot');
      if (!btn) return;
      e.preventDefault();
      if (open && open.btn === btn) { close(); return; }
      openCard(btn);
    });
    // clicks inside a card (e.g. the Shop link) shouldn't close it before navigating
    wrap.addEventListener('click', function (e) {
      if (!e.target.closest('.hotspot-card') && !e.target.closest('.hotspot')) close();
    });
    document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) close(); });
    document.addEventListener('keydown', function (e) { if (e.key === 'Escape') close(); });
  });
})();