[FIX] website: make navbar content invisible when block invisible
Steps to reproduce: 1. Go to the website 2. Add website languages 3. Drag Table Of Content 4. Select snippet block 5. Go to customize the block 6. Select visibility conditionally - set visible/hide for languages. Before the commit, selecting block visibility conditionally makes only the block is invisible but not the navbar content is invisible due to the absence of the `data-visibility-id` attribute. In this commit, handling conditional visibility of the navbar when the the snippet block is invisible. Also, This commit adds a check for missing visibility IDs in anchor links. The code checks if both the visibility ID values exist or if they are both missing. If either condition is met, the function returns without creating the `<a>` tag. task-3373943 closes odoo/odoo#137081 X-original-commit: 182d3f20d8d3ae8149280ac3084423ba11e0975d Signed-off-by: Romain Derie (rde) <rde@odoo.com>
This commit is contained in:
@@ -19,6 +19,8 @@ options.registry.TableOfContent = options.Class.extend({
|
||||
const config = {attributes: false, childList: true, subtree: true, characterData: true};
|
||||
this.observer = new MutationObserver(() => this._generateNav());
|
||||
this.observer.observe(targetNode, config);
|
||||
// The mutation observer doesn't observe the attributes change, it would
|
||||
// be too much. Adding content_changed "listener" instead.
|
||||
this.$target.on('content_changed', () => this._generateNav());
|
||||
return this._super(...arguments);
|
||||
},
|
||||
@@ -89,11 +91,20 @@ options.registry.TableOfContent = options.Class.extend({
|
||||
return;
|
||||
}
|
||||
this.options.wysiwyg && this.options.wysiwyg.odooEditor.unbreakableStepUnactive();
|
||||
const navEl = this.$target[0].querySelector('.s_table_of_content_navbar');
|
||||
const headingsEls = this.$target.find(this.targetedElements).toArray()
|
||||
.filter(el => !el.closest('.o_snippet_desktop_invisible'));
|
||||
const areHeadingsEqual = this.oldHeadingsEls.length === headingsEls.length
|
||||
&& this.oldHeadingsEls.every((el, i) => el.isEqualNode(headingsEls[i]));
|
||||
if (areHeadingsEqual) {
|
||||
const areVisibilityIdsEqual = headingsEls.every((headingEl) => {
|
||||
const visibilityId = headingEl.closest('section').getAttribute('data-visibility-id');
|
||||
const matchingLinkEl = navEl.querySelector(`a[href="#${headingEl.getAttribute('id')}"]`);
|
||||
const matchingLinkVisibilityId = matchingLinkEl ? matchingLinkEl.getAttribute('data-visibility-id') : null;
|
||||
// Check if visibilityId matches matchingLinkVisibilityId or both
|
||||
// are null/undefined
|
||||
return visibilityId === matchingLinkVisibilityId;
|
||||
});
|
||||
if (areHeadingsEqual && areVisibilityIdsEqual) {
|
||||
// If the content of the navbar before the change of the DOM is
|
||||
// equal to the content of the navbar after the change of the DOM,
|
||||
// then there is no need to regenerate the navbar.
|
||||
@@ -106,15 +117,15 @@ options.registry.TableOfContent = options.Class.extend({
|
||||
}
|
||||
// We dispose the scrollSpy because the navbar will be updated.
|
||||
this._disposeScrollSpy();
|
||||
const $nav = this.$target.find('.s_table_of_content_navbar');
|
||||
$nav.empty();
|
||||
navEl.innerHTML = '';
|
||||
headingsEls.forEach((el) => {
|
||||
const $el = $(el);
|
||||
const id = uniqueId("table_of_content_heading_" + new Date().getTime() + "_");
|
||||
$('<a>').attr('href', "#" + id)
|
||||
const visibilityId = $el.closest('section').attr('data-visibility-id');
|
||||
$('<a>').attr({ 'href': "#" + id, 'data-visibility-id': visibilityId })
|
||||
.addClass('table_of_content_link list-group-item list-group-item-action py-2 border-0 rounded-0')
|
||||
.text($el.text())
|
||||
.appendTo($nav);
|
||||
.appendTo(navEl);
|
||||
$el.attr('id', id);
|
||||
$el[0].dataset.anchor = 'true';
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user