Commit 85bce2f5 authored by Cathie Chen's avatar Cathie Chen
Browse files

Bug 1835671 - Popover: add repeatingHide to hide all popovers until algorithm, r=emilio

parent 8c0f52e5
Loading
Loading
Loading
Loading
+37 −19
Original line number Diff line number Diff line
@@ -15002,6 +15002,18 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint,
    return;
  }
  // https://github.com/whatwg/html/pull/9198
  auto needRepeatingHide = [&]() {
    auto autoList = AutoPopoverList();
    return autoList.Contains(&aEndpoint) &&
           &aEndpoint != autoList.LastElement();
  };
  MOZ_ASSERT((&aEndpoint)->IsElement() &&
             (&aEndpoint)->AsElement()->IsAutoPopover());
  bool repeatingHide = false;
  bool fireEvents = aFireEvents;
  do {
    RefPtr<const Element> lastToHide = nullptr;
    bool foundEndpoint = false;
    for (const Element* popover : AutoPopoverList()) {
@@ -15023,8 +15035,14 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint,
      if (!topmost) {
        break;
      }
    HidePopover(*topmost, aFocusPreviousElement, aFireEvents, IgnoreErrors());
      HidePopover(*topmost, aFocusPreviousElement, fireEvents, IgnoreErrors());
    }
    repeatingHide = needRepeatingHide();
    if (repeatingHide) {
      fireEvents = false;
    }
  } while (repeatingHide);
}
MOZ_CAN_RUN_SCRIPT_BOUNDARY void
+2 −2
Original line number Diff line number Diff line
@@ -3369,9 +3369,9 @@ void nsGenericHTMLElement::ShowPopover(ErrorResult& aRv) {
  bool shouldRestoreFocus = false;
  nsWeakPtr originallyFocusedElement;
  if (IsAutoPopover()) {
    RefPtr<Element> ancestor = GetTopmostPopoverAncestor();
    RefPtr<nsINode> ancestor = GetTopmostPopoverAncestor();
    if (!ancestor) {
      ancestor = document->GetDocumentElement();
      ancestor = document;
    }
    document->HideAllPopoversUntil(*ancestor, false, true);

+27 −0
Original line number Diff line number Diff line
@@ -587,3 +587,30 @@ promise_test(async () => {
  p20.hidePopover(); // Cleanup
},'Show an unrelated popover during "hide popover"');
</script>

<div id=p21 popover>21
  <div id=p22 popover>22</div>
  <div id=p23 popover>23</div>
  <div id=p24 popover>24</div>
</div>

<script>
promise_test(async () => {
  p21.showPopover();
  p22.showPopover();
  let events = [];
  const logEvents = (e) => { events.push(`${e.newState === 'open' ? 'show' : 'hide'} ${e.target.id}`) };
  p22.addEventListener('beforetoggle', (e) => {
    logEvents(e);
    p24.showPopover()
  });
  p23.addEventListener('beforetoggle', logEvents);
  p24.addEventListener('beforetoggle', logEvents);
  p23.showPopover();
  assert_array_equals(events, ['show p23', 'hide p22', 'show p24'], 'hiding p24 does not fire event');
  assert_false(p22.matches(':popover-open'));
  assert_true(p23.matches(':popover-open'));
  assert_false(p24.matches(':popover-open'));
  p21.hidePopover(); // Cleanup
},'Show other auto popover during "hide all popover until"');
</script>