UNPKG

pragma-views2

Version:

238 lines (194 loc) 6.37 kB
import {delayedAnimation} from "./../lib/device-helper.js" import {BaseElement} from "../../baremetal/lib/base-element.js"; class PragmaMenu extends BaseElement { constructor() { super(); this.shortcuts; } static get observedAttributes() { return ["hidden"]; } get hidden() { return this.hasAttribute("hidden"); } set hidden(value) { this._hidden = value; if (this._hidden) { delayedAnimation(250, this, "close").then(() => { this.setAttribute("hidden", ""); this.setAttribute("aria-hidden", "true"); }); } else { this.classList.remove("close"); this.removeAttribute("hidden"); this.setAttribute("aria-hidden", "false"); // Focus when animation completed this.addEventListener("transitionend", () => { this.shortcuts.focusSearch(); }, {once: true}) } } get items() { return this._items; } set items(items) { this._items = items; this.render(); } attributeChangedCallback(name, oldValue, newValue) { if (this.hidden) { this._hidden = true; } else { this._hidden = false; } } close() { this.hidden = true; } async connectedCallback() { super.connectedCallback(); this.registerEvent(window, "hashchange", () => this.close()); if (this.hidden) { this.classList.add("close"); this.setAttribute("aria-hidden", "true"); } else { this.setAttribute("aria-hidden", "false"); } const search = this.querySelector("#menu-search"); if (search) { this.registerEvent(search, "keyup", this.onKeyUp.bind(this)) } const routePath = this.getAttribute("src"); const result = await fetch(routePath).then(result => result.text()); this.items = JSON.parse(result); } disconnectedCallback() { super.disconnectedCallback(); } onKeyUp(event) { const searchValue = event.target.value; const collection = this.querySelectorAll("a"); const anchors = [].slice.call(collection); if (searchValue) { anchors.forEach(item => { if (item.text.toLowerCase().indexOf(searchValue.toLowerCase()) == -1) { item.parentElement.setAttribute("aria-hidden", "true"); } else { item.parentElement.setAttribute("aria-hidden", "false"); } }); } else { anchors.forEach(item => { item.parentElement.setAttribute("aria-hidden", "false"); }); } } open() { this.hidden = false; } render() { let nav = document.createElement("nav"); let ul = document.createElement("ul"); for (let item of this._items) { let li = document.createElement("li"); let a = document.createElement("a"); a.text = item.text; if (item.resource) a.href = `#${item.screen}/${item.resource}`; else a.href = `#${item.screen}`; li.appendChild(a); ul.appendChild(li); } ; nav.setAttribute("role", "navigation"); nav.setAttribute("aria-label", "Main application navigation"); nav.append(ul); this.appendChild(nav); if (!this.shortcuts) { this.shortcuts = new PragmaMenuShortcuts(this); } } toggle() { if (this.hidden) { this.open(); } else { this.close(); } } } class PragmaMenuShortcuts { constructor(element) { this.element = element; this.children = element.querySelectorAll('a'); this.first = this.children.length > 0 ? this.children[0] : null; this.last = this.children.length > 0 ? this.children[this.children.length - 1] : null; this.shortcuts = { "DOWNARROW": 40, "UPARROW": 38, "HOME": 36, "END": 35 }; this.keyUpHandler = this.keyup.bind(this); this.element.addEventListener("keyup", this.keyUpHandler); } currentIndex() { const anchors = [].slice.call(this.children); const selected = document.activeElement; return anchors.indexOf(selected); } focusFirstElement() { this.first.focus(); } focusLastElement() { this.last.focus(); } focusNextElement() { const anchors = [].slice.call(this.children); const currentIndex = this.currentIndex(); const nextIndex = currentIndex + 1; if ((anchors.length > 0) && (nextIndex < anchors.length)) anchors[nextIndex].focus(); else this.first.focus(); } focusPreviousElement() { const anchors = [].slice.call(this.children); const currentIndex = this.currentIndex(); const previousIndex = currentIndex - 1; if ((anchors.length > 0) && (previousIndex >= 0)) anchors[previousIndex].focus(); else this.last.focus(); } focusSearch() { const input = this.element.querySelector("#menu-search"); if (input) input.focus(); } keyup(event) { switch (event.keyCode) { case this.shortcuts.DOWNARROW: this.focusNextElement(); break; case this.shortcuts.UPARROW: this.focusPreviousElement(); break; case this.shortcuts.HOME: this.focusFirstElement(); break; case this.shortcuts.END: this.focusLastElement(); break; default: break; } } } customElements.define('pragma-menu', PragmaMenu);