Commit 333cb069 authored by Phil Hughes's avatar Phil Hughes

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
parent 34da9a0f
...@@ -71,6 +71,7 @@ export const handleLocationHash = () => { ...@@ -71,6 +71,7 @@ export const handleLocationHash = () => {
// This is required to handle non-unicode characters in hash // This is required to handle non-unicode characters in hash
hash = decodeURIComponent(hash); hash = decodeURIComponent(hash);
const target = document.getElementById(hash) || document.getElementById(`user-content-${hash}`);
const fixedTabs = document.querySelector('.js-tabs-affix'); const fixedTabs = document.querySelector('.js-tabs-affix');
const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck'); const fixedDiffStats = document.querySelector('.js-diff-files-changed.is-stuck');
const fixedNav = document.querySelector('.navbar-gitlab'); const fixedNav = document.querySelector('.navbar-gitlab');
...@@ -78,15 +79,10 @@ export const handleLocationHash = () => { ...@@ -78,15 +79,10 @@ export const handleLocationHash = () => {
let adjustment = 0; let adjustment = 0;
if (fixedNav) adjustment -= fixedNav.offsetHeight; 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) { if (target && target.scrollIntoView) {
target.scrollIntoView(true); target.scrollIntoView(true);
window.scrollBy(0, adjustment);
} }
} else {
// only adjust for fixedTabs when not targeting user-generated content
if (fixedTabs) { if (fixedTabs) {
adjustment -= fixedTabs.offsetHeight; adjustment -= fixedTabs.offsetHeight;
} }
...@@ -96,7 +92,6 @@ export const handleLocationHash = () => { ...@@ -96,7 +92,6 @@ export const handleLocationHash = () => {
} }
window.scrollBy(0, adjustment); window.scrollBy(0, adjustment);
}
}; };
// Check if element scrolled into viewport from above or below // Check if element scrolled into viewport from above or below
......
...@@ -84,6 +84,66 @@ describe('common_utils', () => { ...@@ -84,6 +84,66 @@ describe('common_utils', () => {
expectGetElementIdToHaveBeenCalledWith('definição'); expectGetElementIdToHaveBeenCalledWith('definição');
expectGetElementIdToHaveBeenCalledWith('user-content-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', () => { describe('setParamInURL', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment