js/controllers/SelectDialogViewController.js
import ActionControllerDelegate from '~/delegate/ActionControllerDelegate';
import PopoverViewController from '~/controllers/PopoverViewController'
import Template from '~/template/Template';
import {find, forEach} from '~/modern/array';
/**
* State of selection
* @implements {State}
*/
export class SelectState {
/**
* Selection state for id
* @param {string} id trimmed id
* @param {HTMLElement} elem
*/
constructor(id, elem) {
/**
* Identifier for state
* @type {string}
*/
this.id = id;
/**
* Option element
* @type {HTMLElement}
*/
this.elem = elem;
}
/**
* @override
* @return {string}
*/
toString() { return this.id; }
}
/**
* Manages a select dialog drop-down
*/
export default class SelectDialogViewController extends PopoverViewController {
/**
* Creates a select-dialog from an HTML template.
* @param {Template} button Template of a `.select-dialog`
*/
constructor(button) {
let node = button.unique();
let trigger = node.getElementsByClassName("select-trigger")[0];
let view = new Template(
node.getElementsByClassName("drop")[0]
);
super(node, trigger, view);
this._activeValue = node.getElementsByTagName("a")[0];
this._opts = node.getElementsByClassName("opt");
this._opts::forEach(opt => {
opt.tabIndex = 0;
opt.setAttribute("role", "option");
opt.addEventListener("keydown", (event) => {
if (document.activeElement === event.target && event.keyCode == 13) {
this._setState(opt);
}
});
opt.addEventListener("click", (event) => {
this._setState(opt);
}, false);
});
/**
* An action delegate.
* @type {ActionControllerDelegate}
*/
this.delegate = new ActionControllerDelegate();
this._setState(this._opts[0]);
}
_setName(name) {
let child;
while (child = this._activeValue.firstChild) {
this._activeValue.removeChild(child);
}
this._activeValue.appendChild(document.createTextNode(name));
this._activeValue.setAttribute('aria-disables', 'true');
}
_setState(option) {
this._opts::forEach(opt => {
if (opt === option) {
opt.classList.add('state-active');
} else {
opt.classList.remove('state-active');
}
});
let state = option.textContent.trim();
this.delegate.didSetStateTo(this, new SelectState(state, option));
this._setName(state);
this.untrigger();
}
setState(option) {
this._setState(
this._opts::find(opt => opt.textContent.trim() === option)
)
}
}