Skip to content

Commit

Permalink
fix: affixed sidebar offset
Browse files Browse the repository at this point in the history
backported 11fc74d and ea21ef4
  • Loading branch information
YUCLing committed Dec 17, 2024
1 parent 9fe17b3 commit 5642bc3
Showing 1 changed file with 31 additions and 22 deletions.
53 changes: 31 additions & 22 deletions framework/core/js/src/forum/components/AffixedSidebar.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import Component from '../../common/Component';

/**
* The `AffixedSidebar` component uses Bootstrap's "affix" plugin to keep a
* Calculate the height of element with margin.
* @param {HTMLElement} element The element.
* @returns {number} The height of element with margin.
*/
function heightWithMargin(element) {
const style = getComputedStyle(element);
return element.getBoundingClientRect().height + parseInt(style.marginBottom, 10) + parseInt(style.marginTop, 10);
}

/**
* The `AffixedSidebar` component uses sticky position to keep a
* sidebar navigation at the top of the viewport when scrolling.
*
* ### Children
*
* The component must wrap an element that itself wraps an <ul> element, which
* will be "affixed".
*
* @see https://getbootstrap.com/docs/3.4/javascript/#affix
*/
export default class AffixedSidebar extends Component {
view(vnode) {
Expand All @@ -19,35 +27,36 @@ export default class AffixedSidebar extends Component {
oncreate(vnode) {
super.oncreate(vnode);

// Register the affix plugin to execute on every window resize (and trigger)
// Register the affix to execute on every window resize (and trigger)
this.boundOnresize = this.onresize.bind(this);
$(window).on('resize', this.boundOnresize).resize();
window.addEventListener('resize', this.boundOnresize);
window.dispatchEvent(new Event('resize'));
}

onremove(vnode) {
super.onremove(vnode);

$(window).off('resize', this.boundOnresize);
window.removeEventListener('resize', this.boundOnresize);
}

onresize() {
const $sidebar = this.$();
const $header = $('#header');
const $footer = $('#footer');
const $affixElement = $sidebar.find('> ul');

$(window).off('.affix');
$affixElement.removeClass('affix affix-top affix-bottom').removeData('bs.affix');
const header = document.getElementById('header');
const affixElement = this.element.querySelector(':scope > ul');
const pageSidebar = this.element.closest('.Page-sidebar');

// Don't affix the sidebar if it is taller than the viewport (otherwise
// there would be no way to scroll through its content).
if ($sidebar.outerHeight(true) > $(window).height() - $header.outerHeight(true)) return;

$affixElement.affix({
offset: {
top: () => $sidebar.offset().top - $header.outerHeight(true) - parseInt($sidebar.css('margin-top'), 10),
bottom: () => (this.bottom = $footer.outerHeight(true)),
},
});
const enabled = heightWithMargin(this.element) <= window.innerHeight - heightWithMargin(header);
affixElement.classList.toggle('affix', enabled);
if (enabled) {
const top = heightWithMargin(header) + parseInt(getComputedStyle(pageSidebar ?? this.element).marginTop, 10);
affixElement.style.position = 'sticky';
affixElement.style.top = top + 'px';
this.element.style.display = 'initial'; // Workaround for sticky not working
} else {
affixElement.style.position = '';
affixElement.style.top = '';
this.element.style.display = '';
}
}
}
}

0 comments on commit 5642bc3

Please sign in to comment.