Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/third_party/closure/goog/ui/submenurenderer.js
4116 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
/**
8
* @fileoverview Renderer for {@link goog.ui.SubMenu}s.
9
*/
10
11
goog.provide('goog.ui.SubMenuRenderer');
12
13
goog.require('goog.a11y.aria');
14
goog.require('goog.a11y.aria.State');
15
goog.require('goog.asserts');
16
goog.require('goog.dom');
17
goog.require('goog.dom.TagName');
18
goog.require('goog.dom.classlist');
19
goog.require('goog.style');
20
goog.require('goog.ui.Menu');
21
goog.require('goog.ui.MenuItemRenderer');
22
goog.requireType('goog.ui.Control');
23
goog.requireType('goog.ui.ControlContent');
24
goog.requireType('goog.ui.SubMenu');
25
26
27
28
/**
29
* Default renderer for {@link goog.ui.SubMenu}s. Each item has the following
30
* structure:
31
*
32
* <div class="goog-submenu">
33
* ...(menuitem content)...
34
* <div class="goog-menu">
35
* ... (submenu content) ...
36
* </div>
37
* </div>
38
*
39
* @constructor
40
* @extends {goog.ui.MenuItemRenderer}
41
*/
42
goog.ui.SubMenuRenderer = function() {
43
'use strict';
44
goog.ui.MenuItemRenderer.call(this);
45
};
46
goog.inherits(goog.ui.SubMenuRenderer, goog.ui.MenuItemRenderer);
47
goog.addSingletonGetter(goog.ui.SubMenuRenderer);
48
49
50
/**
51
* Default CSS class to be applied to the root element of components rendered
52
* by this renderer.
53
* @type {string}
54
*/
55
goog.ui.SubMenuRenderer.CSS_CLASS = goog.getCssName('goog-submenu');
56
57
58
/**
59
* The CSS class for submenus that displays the submenu arrow.
60
* @type {string}
61
* @private
62
*/
63
goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_ =
64
goog.getCssName('goog-submenu-arrow');
65
66
67
/**
68
* Overrides {@link goog.ui.MenuItemRenderer#createDom} by adding
69
* the additional class 'goog-submenu' to the created element,
70
* and passes the element to {@link goog.ui.SubMenuItemRenderer#addArrow_}
71
* to add an child element that can be styled to show an arrow.
72
* @param {goog.ui.Control} control goog.ui.SubMenu to render.
73
* @return {!Element} Root element for the item.
74
* @override
75
*/
76
goog.ui.SubMenuRenderer.prototype.createDom = function(control) {
77
'use strict';
78
var subMenu = /** @type {goog.ui.SubMenu} */ (control);
79
var element =
80
goog.ui.SubMenuRenderer.superClass_.createDom.call(this, subMenu);
81
goog.asserts.assert(element);
82
goog.dom.classlist.add(element, goog.ui.SubMenuRenderer.CSS_CLASS);
83
this.addArrow_(subMenu, element);
84
return element;
85
};
86
87
88
/**
89
* Overrides {@link goog.ui.MenuItemRenderer#decorate} by adding
90
* the additional class 'goog-submenu' to the decorated element,
91
* and passing the element to {@link goog.ui.SubMenuItemRenderer#addArrow_}
92
* to add a child element that can be styled to show an arrow.
93
* Also searches the element for a child with the class goog-menu. If a
94
* matching child element is found, creates a goog.ui.Menu, uses it to
95
* decorate the child element, and passes that menu to subMenu.setMenu.
96
* @param {goog.ui.Control} control goog.ui.SubMenu to render.
97
* @param {Element} element Element to decorate.
98
* @return {!Element} Root element for the item.
99
* @override
100
*/
101
goog.ui.SubMenuRenderer.prototype.decorate = function(control, element) {
102
'use strict';
103
var subMenu = /** @type {goog.ui.SubMenu} */ (control);
104
element =
105
goog.ui.SubMenuRenderer.superClass_.decorate.call(this, subMenu, element);
106
goog.asserts.assert(element);
107
goog.dom.classlist.add(element, goog.ui.SubMenuRenderer.CSS_CLASS);
108
this.addArrow_(subMenu, element);
109
110
// Search for a child menu and decorate it.
111
var childMenuEls = goog.dom.getElementsByTagNameAndClass(
112
goog.dom.TagName.DIV, goog.getCssName('goog-menu'), element);
113
if (childMenuEls.length) {
114
var childMenu = new goog.ui.Menu(subMenu.getDomHelper());
115
var childMenuEl = childMenuEls[0];
116
// Hide the menu element before attaching it to the document body; see
117
// bug 1089244.
118
goog.style.setElementShown(childMenuEl, false);
119
subMenu.getDomHelper().getDocument().body.appendChild(childMenuEl);
120
childMenu.decorate(childMenuEl);
121
subMenu.setMenu(childMenu, true);
122
}
123
return element;
124
};
125
126
127
/**
128
* Takes a menu item's root element, and sets its content to the given text
129
* caption or DOM structure. Overrides the superclass immplementation by
130
* making sure that the submenu arrow structure is preserved.
131
* @param {Element} element The item's root element.
132
* @param {goog.ui.ControlContent} content Text caption or DOM structure to be
133
* set as the item's content.
134
* @override
135
*/
136
goog.ui.SubMenuRenderer.prototype.setContent = function(element, content) {
137
'use strict';
138
// Save the submenu arrow element, if present.
139
var contentElement = this.getContentElement(element);
140
var arrowElement = contentElement && contentElement.lastChild;
141
goog.ui.SubMenuRenderer.superClass_.setContent.call(this, element, content);
142
// If the arrowElement was there, is no longer there, and really was an arrow,
143
// reappend it.
144
if (arrowElement && contentElement.lastChild != arrowElement &&
145
goog.dom.classlist.contains(
146
/** @type {!Element} */ (arrowElement),
147
goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_)) {
148
contentElement.appendChild(arrowElement);
149
}
150
};
151
152
153
/**
154
* Overrides {@link goog.ui.MenuItemRenderer#initializeDom} to tweak
155
* the DOM structure for the span.goog-submenu-arrow element
156
* depending on the text direction (LTR or RTL). When the SubMenu is RTL
157
* the arrow will be given the additional class of goog-submenu-arrow-rtl,
158
* and the arrow will be moved up to be the first child in the SubMenu's
159
* element. Otherwise the arrow will have the class goog-submenu-arrow-ltr,
160
* and be kept as the last child of the SubMenu's element.
161
* @param {goog.ui.Control} control goog.ui.SubMenu whose DOM is to be
162
* initialized as it enters the document.
163
* @override
164
*/
165
goog.ui.SubMenuRenderer.prototype.initializeDom = function(control) {
166
'use strict';
167
var subMenu = /** @type {goog.ui.SubMenu} */ (control);
168
goog.ui.SubMenuRenderer.superClass_.initializeDom.call(this, subMenu);
169
var element = subMenu.getContentElement();
170
var arrow = subMenu.getDomHelper().getElementsByTagNameAndClass(
171
goog.dom.TagName.SPAN, goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_,
172
element)[0];
173
goog.ui.SubMenuRenderer.setArrowTextContent_(subMenu, arrow);
174
if (arrow != element.lastChild) {
175
element.appendChild(arrow);
176
}
177
var subMenuElement = subMenu.getElement();
178
goog.asserts.assert(
179
subMenuElement, 'The sub menu DOM element cannot be null.');
180
goog.a11y.aria.setState(
181
subMenuElement, goog.a11y.aria.State.HASPOPUP, 'true');
182
};
183
184
185
/**
186
* Appends a child node with the class goog.getCssName('goog-submenu-arrow') or
187
* 'goog-submenu-arrow-rtl' which can be styled to show an arrow.
188
* @param {goog.ui.SubMenu} subMenu SubMenu to render.
189
* @param {Element} element Element to decorate.
190
* @private
191
*/
192
goog.ui.SubMenuRenderer.prototype.addArrow_ = function(subMenu, element) {
193
'use strict';
194
var arrow = subMenu.getDomHelper().createDom(goog.dom.TagName.SPAN);
195
arrow.className = goog.ui.SubMenuRenderer.CSS_CLASS_SUBMENU_;
196
goog.ui.SubMenuRenderer.setArrowTextContent_(subMenu, arrow);
197
this.getContentElement(element).appendChild(arrow);
198
};
199
200
201
/**
202
* The unicode char for a left arrow.
203
* @type {string}
204
* @private
205
*/
206
goog.ui.SubMenuRenderer.LEFT_ARROW_ = '\u25C4';
207
208
209
/**
210
* The unicode char for a right arrow.
211
* @type {string}
212
* @private
213
*/
214
goog.ui.SubMenuRenderer.RIGHT_ARROW_ = '\u25BA';
215
216
217
/**
218
* Set the text content of an arrow.
219
* @param {goog.ui.SubMenu} subMenu The sub menu that owns the arrow.
220
* @param {Element} arrow The arrow element.
221
* @private
222
*/
223
goog.ui.SubMenuRenderer.setArrowTextContent_ = function(subMenu, arrow) {
224
'use strict';
225
// Fix arrow rtl
226
var leftArrow = goog.ui.SubMenuRenderer.LEFT_ARROW_;
227
var rightArrow = goog.ui.SubMenuRenderer.RIGHT_ARROW_;
228
229
goog.asserts.assert(arrow);
230
231
if (subMenu.isRightToLeft()) {
232
goog.dom.classlist.add(arrow, goog.getCssName('goog-submenu-arrow-rtl'));
233
// Unicode character - Black left-pointing pointer iff aligned to end.
234
goog.dom.setTextContent(
235
arrow, subMenu.isAlignedToEnd() ? leftArrow : rightArrow);
236
} else {
237
goog.dom.classlist.remove(arrow, goog.getCssName('goog-submenu-arrow-rtl'));
238
// Unicode character - Black right-pointing pointer iff aligned to end.
239
goog.dom.setTextContent(
240
arrow, subMenu.isAlignedToEnd() ? rightArrow : leftArrow);
241
}
242
};
243
244