123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- /*
- * This content is licensed according to the W3C Software License at
- * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
- */
- var MenuItem = function (domNode, menuObj) {
- if (typeof popupObj !== 'object') {
- popupObj = false;
- }
- this.domNode = domNode;
- this.menu = menuObj;
- this.popupMenu = false;
- this.isMenubarItem = false;
- this.keyCode = Object.freeze({
- 'TAB': 9,
- 'RETURN': 13,
- 'ESC': 27,
- 'SPACE': 32,
- 'PAGEUP': 33,
- 'PAGEDOWN': 34,
- 'END': 35,
- 'HOME': 36,
- 'LEFT': 37,
- 'UP': 38,
- 'RIGHT': 39,
- 'DOWN': 40
- });
- };
- MenuItem.prototype.init = function () {
- this.domNode.tabIndex = -1;
- this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
- this.domNode.addEventListener('click', this.handleClick.bind(this));
- this.domNode.addEventListener('focus', this.handleFocus.bind(this));
- this.domNode.addEventListener('blur', this.handleBlur.bind(this));
- this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
- this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
- // Initialize flyout menu
- var nextElement = this.domNode.nextElementSibling;
- if (nextElement && nextElement.tagName === 'UL') {
- this.popupMenu = new PopupMenu(nextElement, this);
- this.popupMenu.init();
- }
- };
- MenuItem.prototype.isExpanded = function () {
- return this.domNode.getAttribute('aria-expanded') === 'true';
- };
- /* EVENT HANDLERS */
- MenuItem.prototype.handleKeydown = function (event) {
- var tgt = event.currentTarget,
- char = event.key,
- flag = false,
- clickEvent;
- function isPrintableCharacter (str) {
- return str.length === 1 && str.match(/\S/);
- }
- switch (event.keyCode) {
- case this.keyCode.SPACE:
- case this.keyCode.RETURN:
- if (this.popupMenu) {
- this.popupMenu.open();
- this.popupMenu.setFocusToFirstItem();
- }
- else {
- // Create simulated mouse event to mimic the behavior of ATs
- // and let the event handler handleClick do the housekeeping.
- try {
- clickEvent = new MouseEvent('click', {
- 'view': window,
- 'bubbles': true,
- 'cancelable': true
- });
- }
- catch (err) {
- if (document.createEvent) {
- // DOM Level 3 for IE 9+
- clickEvent = document.createEvent('MouseEvents');
- clickEvent.initEvent('click', true, true);
- }
- }
- tgt.dispatchEvent(clickEvent);
- }
- flag = true;
- break;
- case this.keyCode.UP:
- this.menu.setFocusToPreviousItem(this);
- flag = true;
- break;
- case this.keyCode.DOWN:
- this.menu.setFocusToNextItem(this);
- flag = true;
- break;
- case this.keyCode.LEFT:
- this.menu.setFocusToController('previous', true);
- this.menu.close(true);
- flag = true;
- break;
- case this.keyCode.RIGHT:
- if (this.popupMenu) {
- this.popupMenu.open();
- this.popupMenu.setFocusToFirstItem();
- }
- else {
- this.menu.setFocusToController('next', true);
- this.menu.close(true);
- }
- flag = true;
- break;
- case this.keyCode.HOME:
- case this.keyCode.PAGEUP:
- this.menu.setFocusToFirstItem();
- flag = true;
- break;
- case this.keyCode.END:
- case this.keyCode.PAGEDOWN:
- this.menu.setFocusToLastItem();
- flag = true;
- break;
- case this.keyCode.ESC:
- this.menu.setFocusToController();
- this.menu.close(true);
- flag = true;
- break;
- case this.keyCode.TAB:
- this.menu.setFocusToController();
- break;
- default:
- if (isPrintableCharacter(char)) {
- this.menu.setFocusByFirstCharacter(this, char);
- flag = true;
- }
- break;
- }
- if (flag) {
- event.stopPropagation();
- event.preventDefault();
- }
- };
- MenuItem.prototype.setExpanded = function (value) {
- if (value) {
- this.domNode.setAttribute('aria-expanded', 'true');
- }
- else {
- this.domNode.setAttribute('aria-expanded', 'false');
- }
- };
- MenuItem.prototype.handleClick = function (event) {
- this.menu.setFocusToController();
- this.menu.close(true);
- };
- MenuItem.prototype.handleFocus = function (event) {
- this.menu.hasFocus = true;
- };
- MenuItem.prototype.handleBlur = function (event) {
- this.menu.hasFocus = false;
- setTimeout(this.menu.close.bind(this.menu, false), 300);
- };
- MenuItem.prototype.handleMouseover = function (event) {
- this.menu.hasHover = true;
- this.menu.open();
- if (this.popupMenu) {
- this.popupMenu.hasHover = true;
- this.popupMenu.open();
- }
- };
- MenuItem.prototype.handleMouseout = function (event) {
- if (this.popupMenu) {
- this.popupMenu.hasHover = false;
- this.popupMenu.close(true);
- }
- this.menu.hasHover = false;
- setTimeout(this.menu.close.bind(this.menu, false), 300);
- };
|