diff --git a/js/jumpmenu.js b/js/jumpmenu.js index adf93cc..88a3767 100644 --- a/js/jumpmenu.js +++ b/js/jumpmenu.js @@ -1,100 +1,122 @@ class JumpMenuElement extends HTMLElement { - constructor() { - super(); - this._headerTag = this.getAttribute('headerTag'); - this._title = this.sanitize(this.getAttribute('data-title')); - this._initialized = false; - this._maxRetries = 1; // Maximum number of retries for ensuring build - - // Only attach shadow root if within #layout-builder - if (this.closest('#layout-builder')) { - this.attachShadow({ mode: 'open' }); + constructor() { + super(); + this._headerTag = this.getAttribute("headerTag"); + this._title = this.sanitize(this.getAttribute("data-title")); + this._initialized = false; + this._maxRetries = 1; // Maximum number of retries for ensuring build + + // Only attach shadow root if within #layout-builder + if (this.closest("#layout-builder")) { + this.attachShadow({ mode: "open" }); + } + } + + connectedCallback() { + this.setAttribute("headerTag", this._headerTag); + this.setAttribute("data-initialized", "true"); + this._initializeEditorListener(); + this._initialBuild(); + this._ensureBuild(); + } + + disconnectedCallback() { + document.removeEventListener("DOMContentLoaded", this._ensureBuild); } - } - - connectedCallback() { - this.setAttribute('headerTag', this._headerTag); - this.setAttribute('data-initialized', 'true'); - this._initializeEditorListener(); - this._initialBuild(); - this._ensureBuild(); - } - - disconnectedCallback() { - document.removeEventListener('DOMContentLoaded', this._ensureBuild); - } - - static get observedAttributes() { - return ['headertag', 'data-title']; - } - - attributeChangedCallback(name, oldValue, newValue) { - if (name === 'headertag') { - this._headerTag = newValue; + + static get observedAttributes() { + return ["headertag", "data-title"]; } - if (name === 'data-title') { - this._title = this.sanitize(newValue); + + attributeChangedCallback(name, oldValue, newValue) { + if (name === "headertag") { + this._headerTag = newValue; + } + if (name === "data-title") { + this._title = this.sanitize(newValue); + } + this._initialBuild(); + this._ensureBuild(); } - this._initialBuild(); - this._ensureBuild(); - } - - sanitize(input) { - const element = document.createElement('div'); - element.innerText = input; - return element.innerHTML; - } - - createJumps(headers) { - return headers.map(header => { - const textContent = header.textContent.trim(); - const id = textContent.replace(/\s+/g, '-').toLowerCase(); - header.setAttribute('id', id); - return `
Note: Additional headers may be found upon save. If no matching headers found, Jump Menu will be hidden.
' : ''; -// Shadow root needed to dodge jquery in Layout builder - const container = this.shadowRoot || this; - container.innerHTML = ` + + // Collect all headers within the container, excluding those inside 'auxiliary-column' sections + const headers = Array.from( + container.querySelectorAll(this._headerTag) + ).filter((header) => !header.closest(".auxiliary-column")); + + const isVisible = (element) => { + const style = window.getComputedStyle(element); + return ( + style.display !== "none" && + !element.classList.contains("visually-hidden") && + !element.classList.contains("ucb-invisible") + ); + }; + + // Filter out headers that are not visible + const visibleHeaders = headers.filter((header) => { + let parent = header.parentElement; + + while (parent && parent !== container) { + if (!isVisible(parent)) { + return false; + } + parent = parent.parentElement; + } + + if (!isVisible(header)) { + return false; + } + + const firstChild = header.firstElementChild; + if (firstChild && !isVisible(firstChild)) { + return false; + } + + return true; + }); + + return visibleHeaders; + } + + _initialBuild() { + const note = this.closest(".ck-editor__main") + ? "Note: Additional headers may be found upon save. If no matching headers found, Jump Menu will be hidden.
" + : ""; + // Shadow root needed to dodge jquery in Layout builder + const container = this.shadowRoot || this; + container.innerHTML = `