diff --git a/addons/website/static/src/snippets/s_table_of_content/000.js b/addons/website/static/src/snippets/s_table_of_content/000.js index d02d56c2137..059bc790dd1 100644 --- a/addons/website/static/src/snippets/s_table_of_content/000.js +++ b/addons/website/static/src/snippets/s_table_of_content/000.js @@ -25,10 +25,6 @@ const TableOfContent = publicWidget.Widget.extend({ if (indexCallback >= 0) { extraMenuUpdateCallbacks.splice(indexCallback, 1); } - const scrollSpyInstance = ScrollSpy.getInstance(this._scrollingElement); - if (scrollSpyInstance) { - scrollSpyInstance.dispose(); - } this.$el.css('top', ''); this.$el.find('.s_table_of_content_navbar').css('top', ''); this._super(...arguments); @@ -42,6 +38,10 @@ const TableOfContent = publicWidget.Widget.extend({ * @private */ _updateTableOfContentNavbarPosition() { + if (!this.$target[0].querySelector('a.table_of_content_link')) { + // Do not start the scrollspy if the TOC is empty. + return; + } let position = 0; const $fixedElements = $('.o_top_fixed_element'); _.each($fixedElements, el => position += $(el).outerHeight()); diff --git a/addons/website/static/src/snippets/s_table_of_content/options.js b/addons/website/static/src/snippets/s_table_of_content/options.js index ad4fc279ec5..caa09ff3224 100644 --- a/addons/website/static/src/snippets/s_table_of_content/options.js +++ b/addons/website/static/src/snippets/s_table_of_content/options.js @@ -20,6 +20,14 @@ options.registry.TableOfContent = options.Class.extend({ this.observer.observe(targetNode, config); return this._super(...arguments); }, + /** + * @override + */ + onRemove() { + this._disposeScrollSpy(); + const exception = (tocEl) => tocEl === this.$target[0]; + this._activateScrollSpy(exception); + }, /** * @override */ @@ -31,11 +39,38 @@ options.registry.TableOfContent = options.Class.extend({ // Private //-------------------------------------------------------------------------- + /** + * @param {Function} exception + */ + _activateScrollSpy(exception) { + for (const tocEl of this.ownerDocument.querySelectorAll('#wrapwrap .s_table_of_content')) { + if (exception(tocEl)) { + continue; + } + this.trigger_up('widgets_start_request', { + $target: $(tocEl), + editableMode: true, + }); + } + }, + /** + * @private + */ + _disposeScrollSpy() { + const scrollingEl = $().getScrollingElement(this.ownerDocument)[0]; + const scrollSpyInstance = + this.$target[0].ownerDocument.defaultView.ScrollSpy.getInstance(scrollingEl); + if (scrollSpyInstance) { + scrollSpyInstance.dispose(); + } + }, /** * @private */ _generateNav: function (ev) { this.options.wysiwyg && this.options.wysiwyg.odooEditor.unbreakableStepUnactive(); + // We dispose the scrollSpy because the navbar will be updated. + this._disposeScrollSpy(); const $nav = this.$target.find('.s_table_of_content_navbar'); const $headings = this.$target.find(this.targetedElements); $nav.empty(); @@ -49,7 +84,8 @@ options.registry.TableOfContent = options.Class.extend({ $el.attr('id', id); $el[0].dataset.anchor = 'true'; }); - $nav.find('a:first').addClass('active'); + const exception = (tocEl) => !tocEl.querySelector('.s_table_of_content_navbar a'); + this._activateScrollSpy(exception); }, });