[IMP] web, website: remove website menu loading effect

The goal of this commit is to remove the menu fade-in effect
on page load since we can now call the initAutoMoreMenu in
non-lazy JS code.

When 'initAutoMoreMenu' called, images won't be loaded yet,
that's why we add a class: '.o_menu_image_placeholder'
to set a default size on images and once all images are loaded,
we reupdate the menu.

task-2618929

X-original-commit: 6be166df24dedbe4729e1e7bfe6a302713932b74
Part-of: odoo/odoo#77843
This commit is contained in:
xO-Tx
2021-10-05 14:17:13 +00:00
committed by qsm-odoo
parent 92d9c84c83
commit dde609a838
3 changed files with 56 additions and 33 deletions
@@ -11,6 +11,9 @@
* can take => the overflowing (foldable) items are added in the dropdown-menu.
* @param {string} [options.minSize] the menu auto-hide option will be disabled
* if viewport is smaller than minSize.
* @param {Array} [options.images=[]] images to wait for before menu update.
* @param {Array} [options.loadingStyleClasses=[]] list of CSS classes to add while
* updating the menu.
*/
export async function initAutoMoreMenu(el, options) {
if (!el) {
@@ -20,6 +23,8 @@ export async function initAutoMoreMenu(el, options) {
unfoldable: 'none',
maxWidth: false,
minSize: '767',
images: [],
loadingStyleClasses: [],
}, options || {});
const isUserNavbar = el.parentElement.classList.contains('o_main_navbar');
@@ -29,6 +34,11 @@ export async function initAutoMoreMenu(el, options) {
var extraItemsToggle = null;
let debounce;
if (options.images.length) {
await _afterImagesLoading(options.images);
_adapt();
}
const debouncedAdapt = () => {
clearTimeout(debounce);
debounce = setTimeout(_adapt, 250);
@@ -173,6 +183,26 @@ export async function initAutoMoreMenu(el, options) {
el.removeEventListener('dom:autoMoreMenu:adapt', _adapt);
}
function _afterImagesLoading(images) {
const defs = images.map((image) => {
if (image.complete || !image.getClientRects().length) {
return null;
}
return new Promise(function (resolve, reject) {
if (!image.width) {
// The purpose of the 'o_menu_image_placeholder' class is to add a default
// size to non loaded images (on the first update) to prevent flickering.
image.classList.add('o_menu_image_placeholder');
}
image.addEventListener('load', () => {
image.classList.remove('o_menu_image_placeholder');
resolve();
});
});
});
return Promise.all(defs);
}
function _endAutoMoreMenu() {
el.classList.remove(...options.loadingStyleClasses);
}
@@ -7,33 +7,27 @@ import { initAutoMoreMenu } from '@web/legacy/js/core/menu';
*/
document.addEventListener('DOMContentLoaded', async () => {
const header = document.querySelector('header#top');
if (!header || header.classList.contains('o_no_autohide_menu')) {
return;
}
const topMenu = header.querySelector('#top_menu');
const unfoldable = '.divider, .divider ~ li, .o_no_autohide_item, .js_language_selector';
const excludedImagesSelector = '.o_mega_menu, .o_offcanvas_logo_container, .o_lang_flag';
const excludedImages = [...header.querySelectorAll(excludedImagesSelector)];
const images = [...header.querySelectorAll('img')].filter((img) => {
excludedImages.forEach(node => {
if (node.contains(img)) {
return false;
}
});
return img.matches && !img.matches(excludedImagesSelector);
});
const defs = images.map((image) => {
if (image.complete) {
return null;
if (header) {
const topMenu = header.querySelector('#top_menu');
if (header.classList.contains('o_no_autohide_menu')) {
topMenu.classList.remove('o_menu_loading');
return;
}
return new Promise(function (resolve, reject) {
image.addEventListener('load', () => {
resolve();
const unfoldable = '.divider, .divider ~ li, .o_no_autohide_item, .js_language_selector';
const excludedImagesSelector = '.o_mega_menu, .o_offcanvas_logo_container, .o_lang_flag';
const excludedImages = [...header.querySelectorAll(excludedImagesSelector)];
const images = [...header.querySelectorAll('img')].filter((img) => {
excludedImages.forEach(node => {
if (node.contains(img)) {
return false;
}
});
return img.matches && !img.matches(excludedImagesSelector);
});
});
await Promise.all(defs);
initAutoMoreMenu(topMenu, {unfoldable: unfoldable});
topMenu.classList.remove('o_menu_loading');
initAutoMoreMenu(topMenu, {
unfoldable: unfoldable,
images: images,
loadingStyleClasses: ['o_menu_loading']
});
}
});
+6 -7
View File
@@ -207,20 +207,19 @@ body:not(.o_fullscreen) {
.navbar-collapse {
min-width: 0; // Allows it to shrink during loading
}
.nav-item {
transition: opacity 1000ms ease 0s;
}
.btn {
// This was a default bootstrap style before but it was removed from
// the library at some point. It seems important in the header so that
// the header does not flicker during loading.
white-space: nowrap;
}
.o_menu_loading {
.o_menu_image_placeholder {
width: 80px !important;
}
#top_menu {
flex-wrap: nowrap !important;
overflow: hidden !important;
.nav-item {
&.o_menu_loading {
overflow: hidden !important;
opacity: 0 !important;
}
}