@@ -13,30 +13,68 @@ $(function() {
1313 . not ( "[href='#0']" )
1414 . click ( function ( event ) {
1515
16- if ( location . pathname . replace ( / ^ \/ / , "" ) === this . pathname . replace ( / ^ \/ / , "" )
17- && location . hostname === this . hostname ) {
16+ if ( location . pathname . replace ( / ^ \/ / , "" ) === this . pathname . replace ( / ^ \/ / , "" )
17+ && location . hostname === this . hostname ) {
1818
19- var target = $ ( decodeURI ( this . hash ) ) ;
19+ const REM = 16 ; /* 16px */
2020
21- if ( target . length ) {
21+ const hash = decodeURI ( this . hash ) ;
22+ let isFnRef = RegExp ( / ^ # f n r e f : / ) . test ( hash ) ;
23+ let isFn = RegExp ( / ^ # f n : / ) . test ( hash ) ;
24+ let selector = hash . includes ( ":" ) ? hash . replace ( / \: / , "\\:" ) : hash ;
25+ const target = $ ( selector ) ;
2226
23- event . preventDefault ( ) ;
27+ if ( target . length ) {
28+ event . preventDefault ( ) ;
2429
25- $ ( "html, body" ) . animate ( {
26- scrollTop : target . offset ( ) . top
27- } , 800 , function ( ) {
28- var $target = $ ( target ) ;
29- $target . focus ( ) ;
30+ if ( history . pushState ) { /* add hash to URL */
31+ history . pushState ( null , null , hash ) ;
32+ }
33+
34+ let curOffset = $ ( this ) . offset ( ) . top ;
35+ let destOffset = target . offset ( ) . top ;
36+ const scrollUp = ( destOffset < curOffset ) ;
37+ const topbarHeight = $ ( "#topbar-wrapper" ) . outerHeight ( ) ;
3038
31- if ( $target . is ( ":focus" ) ) { /* Checking if the target was focused */
32- return false ;
33- } else {
34- $target . attr ( "tabindex" , "-1" ) ; /* Adding tabindex for elements not focusable */
35- $target . focus ( ) ; /* Set focus again */
39+ if ( scrollUp && isFnRef ) {
40+ /* Avoid the top-bar covering `fnref` when scrolling up
41+ because `fnref` has no `%anchor`(see: module.scss) style. */
42+ destOffset -= ( topbarHeight + REM / 2 ) ;
3643 }
37- } ) ;
44+
45+ $ ( "html,body" ) . animate ( {
46+ scrollTop : destOffset
47+ } , 800 , ( ) => {
48+
49+ var $target = $ ( target ) ;
50+ $target . focus ( ) ;
51+
52+ const SCROLL_MARK = "scroll-focus" ;
53+
54+ /* clean up old scroll mark */
55+ if ( $ ( `[${ SCROLL_MARK } =true]` ) . length ) {
56+ $ ( `[${ SCROLL_MARK } =true]` ) . attr ( SCROLL_MARK , false ) ;
57+ }
58+
59+ /* Clean :target links */
60+ if ( $ ( ":target" ) . length ) { /* element that visited by the URL with hash */
61+ $ ( ":target" ) . attr ( SCROLL_MARK , false ) ;
62+ }
63+
64+ /* set scroll mark to footnotes */
65+ if ( isFn || isFnRef ) {
66+ $target . attr ( SCROLL_MARK , true ) ;
67+ }
68+
69+ if ( $target . is ( ":focus" ) ) { /* Checking if the target was focused */
70+ return false ;
71+ } else {
72+ $target . attr ( "tabindex" , "-1" ) ; /* Adding tabindex for elements not focusable */
73+ $target . focus ( ) ; /* Set focus again */
74+ }
75+ } ) ;
76+ }
3877 }
39- }
4078
41- } ) ; /* click() */
79+ } ) ; /* click() */
4280} ) ;
0 commit comments