4 * Copyright, Moxiecode Systems AB
5 * Released under LGPL License.
7 * License: http://www.tinymce.com/license
8 * Contributing: http://www.tinymce.com/contributing
12 * Creates a new menu button.
14 * @-x-less MenuButton.less
15 * @class tinymce.ui.MenuButton
16 * @extends tinymce.ui.Button
18 define("tinymce/ui/MenuButton", [
22 ], function(Button, Factory, MenuBar) {
25 // TODO: Maybe add as some global function
26 function isChildOf(node, parent) {
28 if (parent === node) {
32 node = node.parentNode;
38 var MenuButton = Button.extend({
40 * Constructs a instance with the specified settings.
43 * @param {Object} settings Name/value object with settings.
45 init: function(settings) {
48 self._renderOpen = true;
49 self._super(settings);
51 self.addClass('menubtn');
53 if (settings.fixedWidth) {
54 self.addClass('fixed-width');
57 self.aria('haspopup', true);
62 * Shows the menu for the button.
66 showMenu: function() {
67 var self = this, settings = self.settings, menu;
69 if (self.menu && self.menu.visible()) {
70 return self.hideMenu();
74 menu = settings.menu || [];
76 // Is menu array then auto constuct menu control
83 menu.type = menu.type || 'menu';
86 self.menu = Factory.create(menu).parent(self).renderTo(self.getContainerElm());
87 self.fire('createmenu');
89 self.menu.on('cancel', function(e) {
90 if (e.control === self.menu) {
95 self.menu.on('show hide', function(e) {
96 if (e.control == self.menu) {
97 self.activeMenu(e.type == 'show');
101 self.aria('expanded', true);
105 self.menu.layoutRect({w: self.layoutRect().w});
106 self.menu.moveRel(self.getEl(), ['bl-tl', 'tl-bl']);
110 * Hides the menu for the button.
114 hideMenu: function() {
118 self.menu.items().each(function(item) {
125 self.aria('expanded', false);
130 * Sets the active menu state.
134 activeMenu: function(state) {
135 this.toggleClass('active', state);
139 * Renders the control as a HTML string.
142 * @return {String} HTML representing the control.
144 renderHtml: function() {
145 var self = this, id = self._id, prefix = self.classPrefix;
146 var icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';
148 self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');
151 '<div id="' + id + '" class="' + self.classes() + '" tabindex="-1">' +
152 '<button id="' + id + '-open" role="presentation" type="button" tabindex="-1">' +
153 (icon ? '<i class="' + icon + '"></i>' : '') +
154 '<span>' + (self._text ? (icon ? ' ' : '') + self.encode(self._text) : '') + '</span>' +
155 ' <i class="' + prefix + 'caret"></i>' +
162 * Gets invoked after the control has been rendered.
166 postRender: function() {
169 self.on('click', function(e) {
170 if (e.control === self && isChildOf(e.target, self.getEl())) {
174 self.menu.items()[0].focus();
179 self.on('mouseenter', function(e) {
180 var overCtrl = e.control, parent = self.parent(), hasVisibleSiblingMenu;
182 if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() == parent) {
183 parent.items().filter('MenuButton').each(function(ctrl) {
184 if (ctrl.hideMenu && ctrl != overCtrl) {
185 if (ctrl.menu && ctrl.menu.visible()) {
186 hasVisibleSiblingMenu = true;
193 if (hasVisibleSiblingMenu) {
194 overCtrl.focus(); // Fix for: #5887
200 return self._super();
204 * Sets/gets the current button text.
207 * @param {String} [text] New button text.
208 * @return {String|tinymce.ui.MenuButton} Current text or current MenuButton instance.
210 text: function(text) {
211 var self = this, i, children;
213 if (self._rendered) {
214 children = self.getEl('open').getElementsByTagName('span');
215 for (i = 0; i < children.length; i++) {
216 children[i].innerHTML = self.encode(text);
220 return this._super(text);
224 * Removes the control and it's menus.