Skip to content
Snippets Groups Projects
Commit 4ca793a3 authored by Louis (loco)'s avatar Louis (loco)
Browse files

[FIX] web, website: restore the use of the scroll to top button


Steps to reproduce the bug:
- Go to the website and edit a page.
- Make sure there is enough content to be able to scroll the page.
- Go to the "Theme" tab and disable the "Show Header" option.
- Click on the footer and enable the "Scroll Top Button".
- Click on "Save".
=> Clicking on the "Scroll To Top" button does nothing.

The "Scroll To Top" button is an anchor with its `href` set to `#top`.
By disabling the "Show Header" option, the header is removed from the
DOM and there is no existing element with `id=top` anymore. To fix
this, the `scrollTo` function has been patched in order to be able to
receive selectors as arguments. In the '#top' and '#bottom' case, those
positions are known and always the same (either at the top of the
document or the bottom of it) so there is no need to have the header or
the footer present in the DOM in order to be able to scroll up to those
positions.

Now that the `scrollTo` function is able to scroll to the top or the
bottom of the page even without header or footer, those two positions
can always be suggested as internal link anchors during link edition.

opw-3133464

closes odoo/odoo#113117

Signed-off-by: default avatarQuentin Smetz (qsm) <qsm@odoo.com>
parent c36607dc
No related branches found
No related tags found
No related merge requests found
......@@ -537,10 +537,15 @@ var dom = {
return size;
},
/**
* @param {HTMLElement} el - the element to stroll to (limitation: if the
* element is using a fixed position, this function cannot work except
* if is the header (with the "top" id) or the footer (with the
* "bottom" id) for which exceptions have been made)
* @param {HTMLElement|string} el - the element to scroll to. If "el" is a
* string, it must be a valid selector of an element in the DOM or
* '#top' or '#bottom'. If it is an HTML element, it must be present
* in the DOM.
* Limitation: if the element is using a fixed position, this
* function cannot work except if is the header (el is then either a
* string set to '#top' or an HTML element with the "top" id) or the
* footer (el is then a string set to '#bottom' or an HTML element
* with the "bottom" id) for which exceptions have been made.
* @param {number} [options] - same as animate of jQuery
* @param {number} [options.extraOffset=0]
* extra offset to add on top of the automatic one (the automatic one
......@@ -552,15 +557,19 @@ var dom = {
*/
scrollTo(el, options = {}) {
const $el = $(el);
const $scrollable = $el.parent().closestScrollable();
if (typeof(el) === 'string' && $el[0]) {
el = $el[0];
}
const isTopOrBottomHidden = (el === '#top' || el === '#bottom');
const $topLevelScrollable = $().getScrollingElement();
const $scrollable = isTopOrBottomHidden ? $topLevelScrollable : $el.parent().closestScrollable();
const isTopScroll = $scrollable.is($topLevelScrollable);
function _computeScrollTop() {
if (el.id === 'top') {
if (el === '#top' || el.id === 'top') {
return 0;
}
if (el.id === 'bottom') {
if (el === '#bottom' || el.id === 'bottom') {
return $scrollable[0].scrollHeight - $scrollable[0].clientHeight;
}
......@@ -595,7 +604,8 @@ var dom = {
options.progress.apply(this, ...arguments);
}
const newScrollTop = _computeScrollTop();
if (Math.abs(newScrollTop - originalScrollTop) <= 1.0 && !(el.classList.contains('o_transitioning'))) {
if (Math.abs(newScrollTop - originalScrollTop) <= 1.0
&& (isTopOrBottomHidden || !(el.classList.contains('o_transitioning')))) {
return;
}
$scrollable.stop();
......
......@@ -986,6 +986,19 @@ registry.anchorSlide = publicWidget.Widget.extend({
return;
}
var hash = this.$target[0].hash;
if (hash === '#top' || hash === '#bottom') {
// If the anchor targets #top or #bottom, directly call the
// "scrollTo" function. The reason is that the header or the footer
// could have been removed from the DOM. By receiving a string as
// parameter, the "scrollTo" function handles the scroll to the top
// or to the bottom of the document even if the header or the
// footer is removed from the DOM.
dom.scrollTo(hash, {
duration: 500,
extraOffset: this._computeExtraOffset(),
});
return;
}
if (!utils.isValidAnchor(hash)) {
return;
}
......
......@@ -22,9 +22,20 @@ function loadAnchors(url) {
resolve();
}
}).then(function (response) {
return _.map($(response).find('[id][data-anchor=true]'), function (el) {
const anchors = _.map($(response).find('[id][data-anchor=true]'), function (el) {
return '#' + el.id;
});
// Always suggest the top and the bottom of the page as internal link
// anchor even if the header and the footer are not in the DOM. Indeed,
// the "scrollTo" function handles the scroll towards those elements
// even when they are not in the DOM.
if (!anchors.includes('#top')) {
anchors.unshift('#top');
}
if (!anchors.includes('#bottom')) {
anchors.push('#bottom');
}
return anchors;
}).catch(error => {
console.debug(error);
return [];
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment