120 lines
3.4 KiB
JavaScript
120 lines
3.4 KiB
JavaScript
"use strict";
|
|
|
|
// Main application menu bar
|
|
Toolkit.MenuBar = class MenuBar extends Toolkit.Panel {
|
|
|
|
// Object constructor
|
|
constructor(application, options) {
|
|
super(application, options);
|
|
|
|
// Configure instance fields
|
|
this.expanded = null;
|
|
this.lastFocus = null;
|
|
this.menuBar = this;
|
|
this.name = options.name || "";
|
|
|
|
// Configure element
|
|
this.element.style.position = "relative";
|
|
this.element.style.zIndex = "1";
|
|
this.element.setAttribute("role", "menubar");
|
|
this.setLayout("flex", {
|
|
direction: "row",
|
|
wrap : "false"
|
|
});
|
|
this.setOverflow("visible", "visible");
|
|
this.element.addEventListener(
|
|
"blur" , e=>this.onblur (e), { capture: true });
|
|
this.element.addEventListener(
|
|
"focus", e=>this.onfocus(e), { capture: true });
|
|
|
|
// Configure properties
|
|
this.setName(this.name);
|
|
application.addComponent(this);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Public Methods //////////////////////////////
|
|
|
|
// Add a component as a child of this container
|
|
add(component, index) {
|
|
super.add(component, index);
|
|
component.child();
|
|
return component;
|
|
}
|
|
|
|
// Create a Menu and associate it with the application and component
|
|
newMenu(options, index) {
|
|
|
|
// Create and add a new menu
|
|
let menu = this.add(new Toolkit.Menu(this.application,options), index);
|
|
menu.element.insertAdjacentElement("afterend", menu.menu.element);
|
|
|
|
// Ensure only the first menu is focusable
|
|
for (let x = 0; x < this.children.length; x++)
|
|
this.children[x].element
|
|
.setAttribute("tabindex", x == 0 ? "0" : "-1");
|
|
|
|
return menu;
|
|
}
|
|
|
|
// Return focus to where it was before the menu was activated
|
|
restoreFocus() {
|
|
if (!this.contains(document.activeElement))
|
|
return;
|
|
let elm = this.lastFocus;
|
|
if (elm == null)
|
|
elm = document.body;
|
|
elm.focus();
|
|
if (this.contains(document.activeElement))
|
|
document.activeElement.blur();
|
|
}
|
|
|
|
// Specify the menu's accessible name
|
|
setName(name) {
|
|
this.name = name || "";
|
|
this.localize();
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Package Methods /////////////////////////////
|
|
|
|
// Blur event capture
|
|
onblur(e) {
|
|
if (this.contains(e.relatedTarget))
|
|
return;
|
|
if (this.children.length > 0)
|
|
this.children[0].element.setAttribute("tabindex", "0");
|
|
if (this.expanded != null)
|
|
this.expanded.setExpanded(false);
|
|
}
|
|
|
|
// Focus event capture
|
|
onfocus(e) {
|
|
|
|
// Configure tabstop on the first menu
|
|
if (this.children.length > 0)
|
|
this.children[0].element.setAttribute("tabindex", "-1");
|
|
|
|
// Retain a reference to the previously focused element
|
|
if (this.contains(e.relatedTarget))
|
|
return;
|
|
let from = e.relatedTarget;
|
|
if (from == null)
|
|
from = document.body;
|
|
if ("component" in from)
|
|
from = from.component;
|
|
this.lastFocus = from;
|
|
}
|
|
|
|
// Update display text with localized strings
|
|
localize() {
|
|
let text = this.name;
|
|
if (this.application)
|
|
text = this.application.translate(text, this);
|
|
this.element.setAttribute("aria-label", text);
|
|
}
|
|
|
|
};
|