11import Component from '../../common/Component' ;
2+ import heightWithMargin from '../../common/utils/heightWithMargin' ;
23
34/**
4- * The `AffixedSidebar` component uses Bootstrap's "affix" plugin to keep a
5+ * The `AffixedSidebar` component uses sticky position to keep a
56 * sidebar navigation at the top of the viewport when scrolling.
67 *
78 * ### Children
89 *
910 * The component must wrap an element that itself wraps an <ul> element, which
1011 * will be "affixed".
11- *
12- * @see https://getbootstrap.com/docs/3.4/javascript/#affix
1312 */
1413export default class AffixedSidebar extends Component {
1514 view ( vnode ) {
@@ -19,36 +18,35 @@ export default class AffixedSidebar extends Component {
1918 oncreate ( vnode ) {
2019 super . oncreate ( vnode ) ;
2120
22- // Register the affix plugin to execute on every window resize (and trigger)
21+ // Register the affix to execute on every window resize (and trigger)
2322 this . boundOnresize = this . onresize . bind ( this ) ;
24- $ ( window ) . on ( 'resize' , this . boundOnresize ) . resize ( ) ;
23+ window . addEventListener ( 'resize' , this . boundOnresize ) ;
24+ window . dispatchEvent ( new Event ( 'resize' ) ) ;
2525 }
2626
2727 onremove ( vnode ) {
2828 super . onremove ( vnode ) ;
2929
30- $ ( window ) . off ( 'resize' , this . boundOnresize ) ;
30+ window . removeEventListener ( 'resize' , this . boundOnresize ) ;
3131 }
3232
3333 onresize ( ) {
34- return ;
35- const $sidebar = this . $ ( ) ;
36- const $header = $ ( '#header' ) ;
37- const $footer = $ ( '#footer' ) ;
38- const $affixElement = $sidebar . find ( '> ul' ) ;
39-
40- $ ( window ) . off ( '.affix' ) ;
41- $affixElement . removeClass ( 'affix affix-top affix-bottom' ) . removeData ( 'bs.affix' ) ;
34+ const header = document . getElementById ( 'header' ) ;
35+ const affixElement = this . element . querySelector ( ':scope > ul' ) ;
4236
4337 // Don't affix the sidebar if it is taller than the viewport (otherwise
4438 // there would be no way to scroll through its content).
45- if ( $sidebar . outerHeight ( true ) > $ ( window ) . height ( ) - $header . outerHeight ( true ) ) return ;
46-
47- $affixElement . affix ( {
48- offset : {
49- top : ( ) => $sidebar . offset ( ) . top - $header . outerHeight ( true ) - parseInt ( $sidebar . css ( 'margin-top' ) , 10 ) ,
50- bottom : ( ) => ( this . bottom = $footer . outerHeight ( true ) ) ,
51- } ,
52- } ) ;
39+ const enabled = heightWithMargin ( this . element ) <= window . innerHeight - heightWithMargin ( header ) ;
40+ affixElement . classList . toggle ( 'affix' , enabled ) ;
41+ if ( enabled ) {
42+ const top = heightWithMargin ( header ) + parseInt ( getComputedStyle ( this . element ) . marginTop , 10 ) ;
43+ affixElement . style . position = 'sticky' ;
44+ affixElement . style . top = top + 'px' ;
45+ this . element . style . display = 'initial' ; // Workaround for sticky not working
46+ } else {
47+ affixElement . style . position = '' ;
48+ affixElement . style . top = '' ;
49+ this . element . style . display = '' ;
50+ }
5351 }
5452}
0 commit comments