Fixed anchored content not being scrolled into view
Correctly scrolls anchored content into view when the user loads the page. This is most obvious when the user loads a link note in a merge request & the page does not scroll down to the note. Closes #38326
This commit is contained in:
parent
34da9a0f37
commit
333cb069af
2 changed files with 73 additions and 18 deletions
|
@ -71,6 +71,7 @@ export const handleLocationHash = () => {
|
|||
// This is required to handle non-unicode characters in hash
|
||||
hash = decodeURIComponent(hash);
|
||||
|
||||
const target = document.getElementById(hash) || document.getElementById(`user-content-${hash}`);
|
||||
const fixedTabs = document.querySelector('.js-tabs-affix');
|
||||
const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck');
|
||||
const fixedNav = document.querySelector('.navbar-gitlab');
|
||||
|
@ -78,25 +79,19 @@ export const handleLocationHash = () => {
|
|||
let adjustment = 0;
|
||||
if (fixedNav) adjustment -= fixedNav.offsetHeight;
|
||||
|
||||
// scroll to user-generated markdown anchor if we cannot find a match
|
||||
if (document.getElementById(hash) === null) {
|
||||
const target = document.getElementById(`user-content-${hash}`);
|
||||
if (target && target.scrollIntoView) {
|
||||
target.scrollIntoView(true);
|
||||
window.scrollBy(0, adjustment);
|
||||
}
|
||||
} else {
|
||||
// only adjust for fixedTabs when not targeting user-generated content
|
||||
if (fixedTabs) {
|
||||
adjustment -= fixedTabs.offsetHeight;
|
||||
}
|
||||
|
||||
if (fixedDiffStats) {
|
||||
adjustment -= fixedDiffStats.offsetHeight;
|
||||
}
|
||||
|
||||
window.scrollBy(0, adjustment);
|
||||
if (target && target.scrollIntoView) {
|
||||
target.scrollIntoView(true);
|
||||
}
|
||||
|
||||
if (fixedTabs) {
|
||||
adjustment -= fixedTabs.offsetHeight;
|
||||
}
|
||||
|
||||
if (fixedDiffStats) {
|
||||
adjustment -= fixedDiffStats.offsetHeight;
|
||||
}
|
||||
|
||||
window.scrollBy(0, adjustment);
|
||||
};
|
||||
|
||||
// Check if element scrolled into viewport from above or below
|
||||
|
|
|
@ -84,6 +84,66 @@ describe('common_utils', () => {
|
|||
expectGetElementIdToHaveBeenCalledWith('definição');
|
||||
expectGetElementIdToHaveBeenCalledWith('user-content-definição');
|
||||
});
|
||||
|
||||
it('scrolls element into view', () => {
|
||||
document.body.innerHTML += `
|
||||
<div id="parent">
|
||||
<div style="height: 2000px;"></div>
|
||||
<div id="test" style="height: 2000px;"></div>
|
||||
</div>
|
||||
`;
|
||||
const elTop = document.getElementById('test').getBoundingClientRect().top;
|
||||
|
||||
window.history.pushState({}, null, '#test');
|
||||
commonUtils.handleLocationHash();
|
||||
|
||||
expectGetElementIdToHaveBeenCalledWith('test');
|
||||
expect(window.scrollY).toBe(elTop);
|
||||
|
||||
document.getElementById('parent').remove();
|
||||
});
|
||||
|
||||
it('scrolls user content element into view', () => {
|
||||
document.body.innerHTML += `
|
||||
<div id="parent">
|
||||
<div style="height: 2000px;"></div>
|
||||
<div id="user-content-test" style="height: 2000px;"></div>
|
||||
</div>
|
||||
`;
|
||||
const elTop = document.getElementById('user-content-test').getBoundingClientRect().top;
|
||||
|
||||
window.history.pushState({}, null, '#test');
|
||||
commonUtils.handleLocationHash();
|
||||
|
||||
expectGetElementIdToHaveBeenCalledWith('test');
|
||||
expectGetElementIdToHaveBeenCalledWith('user-content-test');
|
||||
expect(window.scrollY).toBe(elTop);
|
||||
|
||||
document.getElementById('parent').remove();
|
||||
});
|
||||
|
||||
it('scrolls to element with offset from navbar', () => {
|
||||
spyOn(window, 'scrollBy').and.callThrough();
|
||||
document.body.innerHTML += `
|
||||
<div id="parent">
|
||||
<div class="navbar-gitlab" style="position: fixed; top: 0; height: 50px;"></div>
|
||||
<div style="height: 2000px; margin-top: 50px;"></div>
|
||||
<div id="user-content-test" style="height: 2000px;"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const elTop = document.getElementById('user-content-test').getBoundingClientRect().top;
|
||||
|
||||
window.history.pushState({}, null, '#test');
|
||||
commonUtils.handleLocationHash();
|
||||
|
||||
expectGetElementIdToHaveBeenCalledWith('test');
|
||||
expectGetElementIdToHaveBeenCalledWith('user-content-test');
|
||||
expect(window.scrollY).toBe(elTop - 50);
|
||||
expect(window.scrollBy).toHaveBeenCalledWith(0, -50);
|
||||
|
||||
document.getElementById('parent').remove();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setParamInURL', () => {
|
||||
|
|
Loading…
Reference in a new issue