mj-context-menu
Version:
A generic context menu
166 lines • 5.33 kB
JavaScript
import * as MenuUtil from './menu_util.js';
import { HtmlClasses, HtmlAttrs } from './html_classes.js';
import { KEY } from './key_navigatable.js';
export class MenuStore {
constructor(menu) {
this.menu = menu;
this.store = [];
this._active = null;
this.counter = 0;
this.attachedClass = HtmlClasses['ATTACHED'] + '_' + MenuUtil.counter();
this.taborder = true;
this.attrMap = {};
}
set active(element) {
do {
if (this.store.indexOf(element) !== -1) {
this._active = element;
break;
}
element = element.parentNode;
} while (element);
}
get active() {
return this._active;
}
next() {
const length = this.store.length;
if (length === 0) {
this.active = null;
return null;
}
let index = this.store.indexOf(this.active);
index = index === -1 ? 0 : index < length - 1 ? index + 1 : 0;
this.active = this.store[index];
return this.active;
}
previous() {
const length = this.store.length;
if (length === 0) {
this.active = null;
return null;
}
const last = length - 1;
let index = this.store.indexOf(this.active);
index = index === -1 ? last : index === 0 ? last : index - 1;
this.active = this.store[index];
return this.active;
}
clear() {
this.remove(this.store);
}
insert(elementOrList) {
const elements = elementOrList instanceof HTMLElement ? [elementOrList] : elementOrList;
for (const element of elements) {
this.insertElement(element);
}
this.sort();
}
remove(elementOrList) {
const elements = elementOrList instanceof HTMLElement ? [elementOrList] : elementOrList;
for (const element of elements) {
this.removeElement(element);
}
this.sort();
}
inTaborder(flag) {
if (this.taborder && !flag) {
this.removeTaborder();
}
if (!this.taborder && flag) {
this.insertTaborder();
}
this.taborder = flag;
}
insertTaborder() {
if (this.taborder) {
this.insertTaborder_();
}
}
removeTaborder() {
if (this.taborder) {
this.removeTaborder_();
}
}
insertElement(element) {
if (element.classList.contains(this.attachedClass)) {
return;
}
element.classList.add(this.attachedClass);
if (this.taborder) {
this.addTabindex(element);
}
this.addEvents(element);
}
removeElement(element) {
if (!element.classList.contains(this.attachedClass)) {
return;
}
element.classList.remove(this.attachedClass);
if (this.taborder) {
this.removeTabindex(element);
}
this.removeEvents(element);
}
sort() {
const nodes = document.getElementsByClassName(this.attachedClass);
this.store = [].slice.call(nodes);
}
insertTaborder_() {
this.store.forEach((x) => x.setAttribute('tabindex', '0'));
}
removeTaborder_() {
this.store.forEach((x) => x.setAttribute('tabindex', '-1'));
}
addTabindex(element) {
if (element.hasAttribute('tabindex')) {
element.setAttribute(HtmlAttrs['OLDTAB'], element.getAttribute('tabindex'));
}
element.setAttribute('tabindex', '0');
}
removeTabindex(element) {
if (element.hasAttribute(HtmlAttrs['OLDTAB'])) {
element.setAttribute('tabindex', element.getAttribute(HtmlAttrs['OLDTAB']));
element.removeAttribute(HtmlAttrs['OLDTAB']);
}
else {
element.removeAttribute('tabindex');
}
}
addEvents(element) {
if (element.hasAttribute(HtmlAttrs['COUNTER'])) {
return;
}
this.addEvent(element, 'contextmenu', this.menu.post.bind(this.menu));
this.addEvent(element, 'keydown', this.keydown.bind(this));
element.setAttribute(HtmlAttrs['COUNTER'], this.counter.toString());
this.counter++;
}
addEvent(element, name, func) {
const attrName = HtmlAttrs[name.toUpperCase() + 'FUNC'];
this.attrMap[attrName + this.counter] = func;
element.addEventListener(name, func);
}
removeEvents(element) {
if (!element.hasAttribute(HtmlAttrs['COUNTER'])) {
return;
}
const counter = element.getAttribute(HtmlAttrs['COUNTER']);
this.removeEvent(element, 'contextmenu', counter);
this.removeEvent(element, 'keydown', counter);
element.removeAttribute(HtmlAttrs['COUNTER']);
}
removeEvent(element, name, counter) {
const attrName = HtmlAttrs[name.toUpperCase() + 'FUNC'];
const menuFunc = this.attrMap[attrName + counter];
element.removeEventListener(name, menuFunc);
}
keydown(event) {
if (event.keyCode === KEY.SPACE) {
this.menu.post(event);
event.preventDefault();
event.stopImmediatePropagation();
}
}
}
//# sourceMappingURL=menu_store.js.map