pragma-views2
Version:
238 lines (194 loc) • 6.37 kB
JavaScript
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);