HoverPopover
...

Constructor
...

constructor(parent: HoverParent, targetEl: HTMLElement | null, waitTime?: number);
Important

実は、コンストラクタ内では

this.parent.hoverPopover = this;

という操作は行われていない。この操作は onShow メソッド内で行われる。つまり、実際に popover が表示されるタイミングで親の hoverPopover プロパティにセットされるというわけだ。

Properties
...

hoverEl: HTMLElement
...

targetEl: HTMLElement | null
...

targetElHTMLElement の場合、コンストラクタ内で mouseout イベントハンドラが追加される。これによって、ホバーが外れるとポップアップが消えるようになっている。

一方、targetElnull の場合にはそのようなイベントハンドラはフックされないので、明示的に消そう (`hide`) としないとポップアップが消えないようにできる。

Question

ただし、この場合でも hoverEl にはイベントハンドラが追加される。Quick Preview においてパッと見これが働いているように見えないのはなぜだろうか?

waitTime: number
...

特に指定しないと 300 になる。

state
...

shownPos
...

初期化時は null
`show` メソッド内に

this.shownPos = P_,
this.position(P_),

という箇所がある。

P_F_ という関数でセットさせる。引数として渡されたイベントの clientX, clientY, docP_ に記録する。
F_ は、

  1. onHoverLink 内で呼ばれるか、
  2. HoverPopover の Constructor 内か、`show` 内で window 全体に対する mousemove イベントハンドラとしてセットされる。

onLinkHover を直接読んだ場合は 1. の可能性はない。なるほど、それで Quick Preview でマウスを使って Suggestions > `setSelectedItem` したときにはマウスの位置にポップオーバーが追従していたのか。

mousemove イベントも発火しない場合は?次は targetEl があればそれに準じて位置が計算される。しかし今回はそれも null である。この場合は、

t = {
                                    top: 0,
                                    bottom: 0,
                                    left: 0,
                                    right: 0
                                };

Methods
...

onShow
...

ひとつの HoverParent を親としてもつ HoverPopover のうち、実際に開いているものが高々 1 個に抑えられるようにする(これが HoverParent の目的)ための処理をしている。

if (this.parent.hoverPopover) this.parent.hoverPopover.hide();
this.parent.hoverPopover = this;

onHide
...

if (this.parent.hoverPopover === this) this.parent.hoverPopover = null;

show
...

this.targetEl が存在して document.body の一部である場合、

  • this.stateShown に更新して
  • タイマーや位置などの諸処理を行い
  • this.onShow を呼んで
  • もろもろの処理を行い
  • 最後に this.load する。

hide
...

  • this.stateHidden に更新
  • タイマーやイベントハンドラのクリア処理
  • その他もろもろの処理
  • this.onHide を呼ぶ
  • 最後に this.unload する

position
...

たぶん、このメソッドを monkey patch して、this.shownPos に好きな {x: number, y: number} をセットしてそれを old の引数に渡すことでポップオーバーの表示位置をコントロールできると思う。