@@ -850,18 +850,33 @@ function loadCss(cssUrl) {
850
850
}
851
851
hideNotable ( ) ;
852
852
const ty = e . getAttribute ( "data-ty" ) ;
853
- const tooltip = e . getElementsByClassName ( "notable-traits-tooltip" ) [ 0 ] ;
854
853
const wrapper = document . createElement ( "div" ) ;
855
854
wrapper . innerHTML = "<div class=\"docblock\">" + window . NOTABLE_TRAITS [ ty ] + "</div>" ;
856
- wrapper . className = "notable-traits-tooltiptext" ;
857
- tooltip . appendChild ( wrapper ) ;
858
- const pos = wrapper . getBoundingClientRect ( ) ;
859
- tooltip . removeChild ( wrapper ) ;
860
- wrapper . style . top = ( pos . top + window . scrollY ) + "px" ;
861
- wrapper . style . left = ( pos . left + window . scrollX ) + "px" ;
862
- wrapper . style . width = pos . width + "px" ;
855
+ wrapper . className = "notable popover" ;
856
+ const focusCatcher = document . createElement ( "div" ) ;
857
+ focusCatcher . setAttribute ( "tabindex" , "0" ) ;
858
+ focusCatcher . onfocus = hideNotable ;
859
+ wrapper . appendChild ( focusCatcher ) ;
860
+ const pos = e . getBoundingClientRect ( ) ;
861
+ // 5px overlap so that the mouse can easily travel from place to place
862
+ wrapper . style . top = ( pos . top + window . scrollY + pos . height ) + "px" ;
863
+ wrapper . style . left = 0 ;
864
+ wrapper . style . right = "auto" ;
865
+ wrapper . style . visibility = "hidden" ;
863
866
const body = document . getElementsByTagName ( "body" ) [ 0 ] ;
864
867
body . appendChild ( wrapper ) ;
868
+ const wrapperPos = wrapper . getBoundingClientRect ( ) ;
869
+ // offset so that the arrow points at the center of the "(i)"
870
+ const finalPos = pos . left + window . scrollX - wrapperPos . width + 24 ;
871
+ if ( finalPos > 0 ) {
872
+ wrapper . style . left = finalPos + "px" ;
873
+ } else {
874
+ wrapper . style . setProperty (
875
+ "--popover-arrow-offset" ,
876
+ ( wrapperPos . right - pos . right + 4 ) + "px"
877
+ ) ;
878
+ }
879
+ wrapper . style . visibility = "" ;
865
880
window . CURRENT_NOTABLE_ELEMENT = wrapper ;
866
881
window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE = e ;
867
882
wrapper . onpointerleave = function ( ev ) {
@@ -875,9 +890,31 @@ function loadCss(cssUrl) {
875
890
} ;
876
891
}
877
892
893
+ function notableBlurHandler ( event ) {
894
+ if ( window . CURRENT_NOTABLE_ELEMENT &&
895
+ ! elemIsInParent ( document . activeElement , window . CURRENT_NOTABLE_ELEMENT ) &&
896
+ ! elemIsInParent ( event . relatedTarget , window . CURRENT_NOTABLE_ELEMENT ) &&
897
+ ! elemIsInParent ( document . activeElement , window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE ) &&
898
+ ! elemIsInParent ( event . relatedTarget , window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE )
899
+ ) {
900
+ // Work around a difference in the focus behaviour between Firefox, Chrome, and Safari.
901
+ // When I click the button on an already-opened notable trait popover, Safari
902
+ // hides the popover and then immediately shows it again, while everyone else hides it
903
+ // and it stays hidden.
904
+ //
905
+ // To work around this, make sure the click finishes being dispatched before
906
+ // hiding the popover. Since `hideNotable()` is idempotent, this makes Safari behave
907
+ // consistently with the other two.
908
+ setTimeout ( hideNotable , 0 ) ;
909
+ }
910
+ }
911
+
878
912
function hideNotable ( ) {
879
913
if ( window . CURRENT_NOTABLE_ELEMENT ) {
880
- window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE . NOTABLE_FORCE_VISIBLE = false ;
914
+ if ( window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE . NOTABLE_FORCE_VISIBLE ) {
915
+ window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE . focus ( ) ;
916
+ window . CURRENT_NOTABLE_ELEMENT . NOTABLE_BASE . NOTABLE_FORCE_VISIBLE = false ;
917
+ }
881
918
const body = document . getElementsByTagName ( "body" ) [ 0 ] ;
882
919
body . removeChild ( window . CURRENT_NOTABLE_ELEMENT ) ;
883
920
window . CURRENT_NOTABLE_ELEMENT = null ;
@@ -891,7 +928,11 @@ function loadCss(cssUrl) {
891
928
hideNotable ( ) ;
892
929
} else {
893
930
showNotable ( this ) ;
931
+ window . CURRENT_NOTABLE_ELEMENT . setAttribute ( "tabindex" , "0" ) ;
932
+ window . CURRENT_NOTABLE_ELEMENT . focus ( ) ;
933
+ window . CURRENT_NOTABLE_ELEMENT . onblur = notableBlurHandler ;
894
934
}
935
+ return false ;
895
936
} ;
896
937
e . onpointerenter = function ( ev ) {
897
938
// If this is a synthetic touch event, ignore it. A click event will be along shortly.
@@ -1018,6 +1059,7 @@ function loadCss(cssUrl) {
1018
1059
onEachLazy ( document . querySelectorAll ( ".search-form .popover" ) , elem => {
1019
1060
elem . style . display = "none" ;
1020
1061
} ) ;
1062
+ hideNotable ( ) ;
1021
1063
} ;
1022
1064
1023
1065
/**
0 commit comments