skip to Main Content

I have a dropdown that I wish to show/hide using html popover API under many different elements. The problem is that popover uses id to detect the target, obviously I can’t use one id on multiple elements. Is there a way to address this issue so I don’t need to hard code the id, using different ids, for each single element?

This is my dropdown that I want to use on multiple, different, elements:

<div popover id="menu">
    ..dropdown content...
</div>

I have this btn on different elements:

<button id="btn" popovertarget="menu"></button>

so the thing I want is to be able to open/close the dropdown, specific to the element that the btn was clicked on. Something like below:

<!-- element 1 -->
<div>
  <button id="btn" popovertarget="menu"></button>
  <div popover id="menu">
    ..dropdown content - same for all elements...
  </div>
</div>

<!-- element 2 -->
<div>
  <button id="btn" popovertarget="menu"></button>
  <div popover id="menu">
    ..dropdown content - same for all elements...
  </div>
</div>

<!-- element 3 -->
<div>
  <button id="btn" popovertarget="menu"></button>
  <div popover id="menu">
    ..dropdown content - same for all elements...
  </div>
</div>

By doing the above, only one btn works to show/hide the dropdown, which is not what I want.

2

Answers


  1. Chosen as BEST ANSWER

    So this is the way I'm doing it now, using html popover and css anchor API.

    if (window.innerWidth >= 640) {
      document.querySelectorAll('.dots-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          // btn rect
          const btnOffsetTop = btn.offsetTop;
          const btnOffsetLeft = btn.offsetLeft;
    
          // find the specific popover
          const popoverId = btn.getAttribute('popovertarget');
          const popover = document.getElementById(popoverId);
    
          if (CSS.supports('position-anchor', 'unset')) {
            // anchor the popover to btn
            popover.style.positionAnchor = `--${popoverId}-btn`;
            btn.style.anchorName = `--${popoverId}-btn`;
          } else {
            // fallback for browsers that don't support html popover
            popover.style.left = `${btnOffsetLeft - 130}px`;
            if (window.innerHeight - btn.getBoundingClientRect().bottom < 350) {
              popover.style.top = `${btnOffsetTop - 300}px`;
            } else {
              popover.style.top = `${btnOffsetTop + 100}px`;
            }
          }
        });
      });


  2. You can use the showPopover, hidePopover methods to show/hide popover using JS instead of direct html.
    That will allow you to target same popover from multiple elements and set it’s position using the target element.

    https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/showPopover

    Here is a sample, you will need to update logic as per your case.

    const sBtn1 = document.getElementById("submit1");
    const sBtn2 = document.getElementById("submit2");
    const outSpan = document.getElementById("menu");
    
    function pop() {
    let targetid = event.target.id;
    let positiony = event.target.offsetTop;
    let positionx = event.target.offsetLeft;
    
    outSpan.style.top = `${positiony + 50}px`;
    outSpan.style.left = `${positionx + 50}px`;
    console.log(outSpan.style.top, outSpan.style.left);
    outSpan.togglePopover();
    }
    <button id=submit1 onclick="pop()">Submit</button>
    <button id=submit2 onclick="pop()">Submit</button>
    <div popover="manual" id="menu" >
        ..dropdown content - same for all elements...
      </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search