flatmenubuttonrenderer.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Similar functionality of {@link goog.ui.MenuButtonRenderer},
  16. * but inherits from {@link goog.ui.FlatButtonRenderer} instead of
  17. * {@link goog.ui.CustomButtonRenderer}. This creates a simpler menu button
  18. * that will look more like a traditional <select> menu.
  19. *
  20. */
  21. goog.provide('goog.ui.FlatMenuButtonRenderer');
  22. goog.require('goog.dom');
  23. goog.require('goog.dom.TagName');
  24. goog.require('goog.style');
  25. goog.require('goog.ui.FlatButtonRenderer');
  26. goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
  27. goog.require('goog.ui.Menu');
  28. goog.require('goog.ui.MenuButton');
  29. goog.require('goog.ui.MenuRenderer');
  30. goog.require('goog.ui.registry');
  31. /**
  32. * Flat Menu Button renderer. Creates a simpler version of
  33. * {@link goog.ui.MenuButton} that doesn't look like a button and
  34. * doesn't have rounded corners. Uses just a `<div>` and looks more like
  35. * a traditional `<select>` element.
  36. * @constructor
  37. * @extends {goog.ui.FlatButtonRenderer}
  38. */
  39. goog.ui.FlatMenuButtonRenderer = function() {
  40. goog.ui.FlatButtonRenderer.call(this);
  41. };
  42. goog.inherits(goog.ui.FlatMenuButtonRenderer, goog.ui.FlatButtonRenderer);
  43. goog.addSingletonGetter(goog.ui.FlatMenuButtonRenderer);
  44. /**
  45. * Default CSS class to be applied to the root element of components rendered
  46. * by this renderer.
  47. * @type {string}
  48. */
  49. goog.ui.FlatMenuButtonRenderer.CSS_CLASS =
  50. goog.getCssName('goog-flat-menu-button');
  51. /**
  52. * Returns the button's contents wrapped in the following DOM structure:
  53. *
  54. * <div class="goog-inline-block goog-flat-menu-button">
  55. * <div class="goog-inline-block goog-flat-menu-button-caption">
  56. * Contents...
  57. * </div>
  58. * <div class="goog-inline-block goog-flat-menu-button-dropdown">
  59. * &nbsp;
  60. * </div>
  61. * </div>
  62. *
  63. * Overrides {@link goog.ui.FlatButtonRenderer#createDom}.
  64. * @param {goog.ui.Control} control Button to render.
  65. * @return {!Element} Root element for the button.
  66. * @override
  67. */
  68. goog.ui.FlatMenuButtonRenderer.prototype.createDom = function(control) {
  69. var button = /** @type {goog.ui.Button} */ (control);
  70. var classNames = this.getClassNames(button);
  71. var element = button.getDomHelper().createDom(
  72. goog.dom.TagName.DIV,
  73. goog.ui.INLINE_BLOCK_CLASSNAME + ' ' + classNames.join(' '), [
  74. this.createCaption(button.getContent(), button.getDomHelper()),
  75. this.createDropdown(button.getDomHelper())
  76. ]);
  77. this.setTooltip(element, /** @type {!string}*/ (button.getTooltip()));
  78. return element;
  79. };
  80. /**
  81. * Takes the button's root element and returns the parent element of the
  82. * button's contents.
  83. * @param {Element} element Root element of the button whose content
  84. * element is to be returned.
  85. * @return {Element} The button's content element (if any).
  86. * @override
  87. */
  88. goog.ui.FlatMenuButtonRenderer.prototype.getContentElement = function(element) {
  89. return element && /** @type {Element} */ (element.firstChild);
  90. };
  91. /**
  92. * Takes an element, decorates it with the menu button control, and returns
  93. * the element. Overrides {@link goog.ui.CustomButtonRenderer#decorate} by
  94. * looking for a child element that can be decorated by a menu, and if it
  95. * finds one, decorates it and attaches it to the menu button.
  96. * @param {goog.ui.Control} button Menu button to decorate the element.
  97. * @param {Element} element Element to decorate.
  98. * @return {Element} Decorated element.
  99. * @override
  100. */
  101. goog.ui.FlatMenuButtonRenderer.prototype.decorate = function(button, element) {
  102. // TODO(user): MenuButtonRenderer uses the exact same code.
  103. // Refactor this block to its own module where both can use it.
  104. var menuElem = goog.dom.getElementsByTagNameAndClass(
  105. '*', goog.ui.MenuRenderer.CSS_CLASS, element)[0];
  106. if (menuElem) {
  107. // Move the menu element directly under the body, but hide it first; see
  108. // bug 1089244.
  109. goog.style.setElementShown(menuElem, false);
  110. button.getDomHelper().getDocument().body.appendChild(menuElem);
  111. // Decorate the menu and attach it to the button.
  112. var menu = new goog.ui.Menu();
  113. menu.decorate(menuElem);
  114. button.setMenu(menu);
  115. }
  116. // Add the caption if it's not already there.
  117. var captionElem = goog.dom.getElementsByTagNameAndClass(
  118. '*', goog.getCssName(this.getCssClass(), 'caption'), element)[0];
  119. if (!captionElem) {
  120. element.appendChild(
  121. this.createCaption(element.childNodes, button.getDomHelper()));
  122. }
  123. // Add the dropdown icon if it's not already there.
  124. var dropdownElem = goog.dom.getElementsByTagNameAndClass(
  125. '*', goog.getCssName(this.getCssClass(), 'dropdown'), element)[0];
  126. if (!dropdownElem) {
  127. element.appendChild(this.createDropdown(button.getDomHelper()));
  128. }
  129. // Let the superclass do the rest.
  130. return goog.ui.FlatMenuButtonRenderer.superClass_.decorate.call(
  131. this, button, element);
  132. };
  133. /**
  134. * Takes a text caption or existing DOM structure, and returns it wrapped in
  135. * an appropriately-styled DIV. Creates the following DOM structure:
  136. *
  137. * <div class="goog-inline-block goog-flat-menu-button-caption">
  138. * Contents...
  139. * </div>
  140. *
  141. * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
  142. * in a box.
  143. * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
  144. * @return {Element} Caption element.
  145. */
  146. goog.ui.FlatMenuButtonRenderer.prototype.createCaption = function(
  147. content, dom) {
  148. return dom.createDom(
  149. goog.dom.TagName.DIV, goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
  150. goog.getCssName(this.getCssClass(), 'caption'),
  151. content);
  152. };
  153. /**
  154. * Returns an appropriately-styled DIV containing a dropdown arrow element.
  155. * Creates the following DOM structure:
  156. *
  157. * <div class="goog-inline-block goog-flat-menu-button-dropdown">
  158. * &nbsp;
  159. * </div>
  160. *
  161. * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
  162. * @return {!Element} Dropdown element.
  163. */
  164. goog.ui.FlatMenuButtonRenderer.prototype.createDropdown = function(dom) {
  165. // 00A0 is &nbsp;
  166. return dom.createDom(
  167. goog.dom.TagName.DIV, {
  168. 'class': goog.ui.INLINE_BLOCK_CLASSNAME + ' ' +
  169. goog.getCssName(this.getCssClass(), 'dropdown'),
  170. 'aria-hidden': true
  171. },
  172. '\u00A0');
  173. };
  174. /**
  175. * Returns the CSS class to be applied to the root element of components
  176. * rendered using this renderer.
  177. * @return {string} Renderer-specific CSS class.
  178. * @override
  179. */
  180. goog.ui.FlatMenuButtonRenderer.prototype.getCssClass = function() {
  181. return goog.ui.FlatMenuButtonRenderer.CSS_CLASS;
  182. };
  183. // Register a decorator factory function for Flat Menu Buttons.
  184. goog.ui.registry.setDecoratorByClassName(
  185. goog.ui.FlatMenuButtonRenderer.CSS_CLASS, function() {
  186. // Uses goog.ui.MenuButton, but with FlatMenuButtonRenderer.
  187. return new goog.ui.MenuButton(
  188. null, null, goog.ui.FlatMenuButtonRenderer.getInstance());
  189. });