Skip to content

Commit

Permalink
Close #765. Store a reference to the tooltip/popover on insert so tha…
Browse files Browse the repository at this point in the history
…t we can more reliably use it to restore when hidden
  • Loading branch information
cpsievert committed Aug 25, 2023
1 parent a4e487c commit 632d459
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 21 deletions.
23 changes: 11 additions & 12 deletions srcts/src/components/popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,8 @@ type MessageData = ToggleMessage | UpdateMessage;

export class BslibPopover extends BslibElement {
static tagName = "bslib-popover";
// Although it isn't included in the type, Bootstrap hangs a tip element off
// of the popover instance, which provides a convenient way to find where the
// popover is located in the DOM.
private bsPopover!: PopoverType & { tip?: HTMLElement };
private bsPopoverEl!: HTMLElement;
private visibilityObserver!: IntersectionObserver;
private static shinyResizeObserver = new ShinyResizeObserver();

Expand Down Expand Up @@ -224,7 +222,13 @@ export class BslibPopover extends BslibElement {

private _onInsert(): void {
const { tip } = this.bsPopover;
if (!tip) return;
if (!tip) {
throw new Error(
"Failed to find the popover's DOM element. Please report this bug."
);
}

this.bsPopoverEl = tip;

// If outputs happen to be in the tooltip, make sure they sized correctly
BslibPopover.shinyResizeObserver.observe(tip);
Expand Down Expand Up @@ -282,15 +286,10 @@ export class BslibPopover extends BslibElement {
// when the popover is hidden, we're responsible for moving it back to this
// element.
private _restoreContent(): void {
const { tip } = this.bsPopover;
if (!tip) {
throw new Error(
"Failed to find the popover's DOM element. Please report this bug."
);
}
const body = tip.querySelector(".popover-body");
const el = this.bsPopoverEl;
const body = el.querySelector(".popover-body");
if (body) this.contentContainer.append(body?.firstChild as HTMLElement);
const header = tip.querySelector(".popover-header");
const header = el.querySelector(".popover-header");
if (header) this.contentContainer.append(header?.firstChild as HTMLElement);
}

Expand Down
23 changes: 14 additions & 9 deletions srcts/src/components/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type MessageData = ToggleMessage | UpdateMessage;
export class BslibTooltip extends BslibElement {
static tagName = "bslib-tooltip";
private bsTooltip!: TooltipType & { tip?: HTMLElement };
private bsTooltipEl!: HTMLElement;
private visibilityObserver!: IntersectionObserver;
private static shinyResizeObserver = new ShinyResizeObserver();

Expand Down Expand Up @@ -134,7 +135,16 @@ export class BslibTooltip extends BslibElement {

private _onInsert(): void {
const { tip } = this.bsTooltip;
if (!tip) return;
if (!tip) {
throw new Error(
"Failed to find the tooltip's DOM element. Please report this bug."
);
}

// Store a reference to the tooltip's DOM element so that we can use it
// later to _restoreContent() (i.e., bring the tooltip contents back to
// this element)
this.bsTooltipEl = tip;

// If outputs happen to be in the tooltip, make sure they sized correctly
BslibTooltip.shinyResizeObserver.observe(tip);
Expand All @@ -151,18 +161,13 @@ export class BslibTooltip extends BslibElement {
}

// Since this.content is an HTMLElement, when it's shown bootstrap.Popover()
// will move the DOM element from this web container to the popover's
// will move the DOM element from this web container to the tooltip's
// container (which, by default, is the body, but can also be customized). So,
// when the popover is hidden, we're responsible for moving it back to this
// element.
private _restoreContent(): void {
const { tip } = this.bsTooltip;
if (!tip) {
throw new Error(
"Failed to find the popover's DOM element. Please report this bug."
);
}
const content = tip.querySelector(".tooltip-inner")?.firstChild;
const el = this.bsTooltipEl;
const content = el.querySelector(".tooltip-inner")?.firstChild;
if (content instanceof HTMLElement) {
content.style.display = "none";
this.prepend(content);
Expand Down

0 comments on commit 632d459

Please sign in to comment.