PageSourceSearch

https://www.aragon.es/o/aragon-theme/js/aria/MenubarItemAction.js

js aragon.es collected 2026-09-24 08:28:22 UTC 4,866 bytes, 176 lines download raw bytes

1export function MenubarItemAction(aria) {
2  /*
3  *   This content is licensed according to the W3C Software License at
4  *   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
5  *
6  *   File:   MenubarItemAction.js
7  *
8  *   Desc:   Menubar Menuitem widget that implements ARIA Authoring Practices
9  */
10
11  /*
12  *   @constructor MenubarItemAction
13  *
14  *   @desc
15  *       Object that configures menubar item elements by setting tabIndex
16  *       and registering itself to handle pertinent events.
17  *
18  *   @param domNode
19  *       The DOM element node that serves as the menubar item container.
20  *       The menubarObj is responsible for checking that it has
21  *       requisite metadata, e.g. role="menuitem".
22  *
23  *   @param menubarObj
24  *       The MenubarAction object that is a delegate for the menubar DOM element
25  *       that contains the menubar item element.
26  */
27  aria.MenubarItemAction = function (domNode, menubarObj) {
28
29    this.menubar = menubarObj;
30    this.domNode = domNode;
31    this.popupMenu = false;
32
33    this.keyCode = Object.freeze({
34      'TAB': 9,
35      'RETURN': 13,
36      'ESC': 27,
37      'SPACE': 32,
38      'PAGEUP': 33,
39      'PAGEDOWN': 34,
40      'END': 35,
41      'HOME': 36,
42      'LEFT': 37,
43      'UP': 38,
44      'RIGHT': 39,
45      'DOWN': 40
46    });
47  };
48
49  aria.MenubarItemAction.prototype.init = function () {
50    this.domNode.tabIndex = -1;
51
52    this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
53    this.domNode.addEventListener('click', this.handleClick.bind(this));
54    this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
55
56    // initialize pop up menus
57
58    var nextElement = this.domNode.nextElementSibling;
59
60    if (nextElement && nextElement.tagName === 'UL') {
61      this.popupMenu = new aria.PopupMenuAction(nextElement, this, this.menubar.actionManager);
62      this.popupMenu.init();
63    }
64
65  };
66
67  aria.MenubarItemAction.prototype.handleKeydown = function (event) {
68    var tgt = event.currentTarget,
69      char = event.key,
70      flag = false;
71
72    function isPrintableCharacter (str) {
73      return str.length === 1 && str.match(/\S/);
74    }
75
76    switch (event.keyCode) {
77      case this.keyCode.SPACE:
78      case this.keyCode.RETURN:
79      case this.keyCode.DOWN:
80        if (this.popupMenu) {
81          this.popupMenu.open();
82          this.popupMenu.setFocusToFirstItem();
83          flag = true;
84        }
85        break;
86
87      case this.keyCode.ESC:
88        if (this.popupMenu) {
89          this.popupMenu.close();
90        }
91        flag = true;
92        break;
93
94      case this.keyCode.LEFT:
95        this.menubar.setFocusToPreviousItem(this);
96        flag = true;
97        break;
98
99      case this.keyCode.RIGHT:
100        this.menubar.setFocusToNextItem(this);
101        flag = true;
102        break;
103
104      case this.keyCode.UP:
105        if (this.popupMenu) {
106          this.popupMenu.open();
107          this.popupMenu.setFocusToLastItem();
108          flag = true;
109        }
110        break;
111
112      case this.keyCode.HOME:
113      case this.keyCode.PAGEUP:
114        this.menubar.setFocusToFirstItem();
115        if (this.popupMenu) {
116          this.popupMenu.close();
117        }
118        flag = true;
119        break;
120
121      case this.keyCode.END:
122      case this.keyCode.PAGEDOWN:
123        this.menubar.setFocusToLastItem();
124        if (this.popupMenu) {
125          this.popupMenu.close();
126        }
127        flag = true;
128        break;
129
130      case this.keyCode.ESC:
131        if (this.popupMenu) {
132          this.popupMenu.close();
133        }
134        flag = true;
135        break;
136
137      default:
138        if (isPrintableCharacter(char)) {
139          this.menubar.setFocusByFirstCharacter(this, char);
140          flag = true;
141        }
142        break;
143    }
144
145    if (flag) {
146      event.stopPropagation();
147      event.preventDefault();
148    }
149  };
150
151  aria.MenubarItemAction.prototype.handleClick = function (event) {
152    if (this.popupMenu) {
153      if (!this.popupMenu.isOpen()) {
154        // clicking on menubar item opens menu (closes open menu first)
155        for (var i = 0; i < this.menubar.menubarItems.length; i++) {
156          var mbi = this.menubar.menubarItems[i];
157          if (mbi.popupMenu && mbi.popupMenu.isOpen()) {
158            mbi.popupMenu.close();
159            break;
160          }
161        }
162        this.popupMenu.open();
163      }
164      else {
165        // clicking again on same menubar item closes menu
166        this.popupMenu.close();
167      }
168      // prevent scroll to top of page when anchor element is clicked
169      event.preventDefault();
170    }
171  };
172
173  aria.MenubarItemAction.prototype.handleMouseover = function (event) {
174    this.menubar.setFocusToItem(this, true);
175  };
176}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.