imagelessbuttonrenderer.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 An alternative custom button renderer that uses even more CSS
  16. * voodoo than the default implementation to render custom buttons with fake
  17. * rounded corners and dimensionality (via a subtle flat shadow on the bottom
  18. * half of the button) without the use of images.
  19. *
  20. * Based on the Custom Buttons 3.1 visual specification, see
  21. * http://go/custombuttons
  22. *
  23. * @author eae@google.com (Emil A Eklund)
  24. * @see ../demos/imagelessbutton.html
  25. */
  26. goog.provide('goog.ui.ImagelessButtonRenderer');
  27. goog.require('goog.dom.TagName');
  28. goog.require('goog.dom.classlist');
  29. goog.require('goog.ui.Button');
  30. goog.require('goog.ui.Component');
  31. goog.require('goog.ui.CustomButtonRenderer');
  32. goog.require('goog.ui.INLINE_BLOCK_CLASSNAME');
  33. goog.require('goog.ui.registry');
  34. /**
  35. * Custom renderer for {@link goog.ui.Button}s. Imageless buttons can contain
  36. * almost arbitrary HTML content, will flow like inline elements, but can be
  37. * styled like block-level elements.
  38. *
  39. * @deprecated These contain a lot of unnecessary DOM for modern user agents.
  40. * Please use a simpler button renderer like css3buttonrenderer.
  41. * @constructor
  42. * @extends {goog.ui.CustomButtonRenderer}
  43. */
  44. goog.ui.ImagelessButtonRenderer = function() {
  45. goog.ui.CustomButtonRenderer.call(this);
  46. };
  47. goog.inherits(goog.ui.ImagelessButtonRenderer, goog.ui.CustomButtonRenderer);
  48. goog.addSingletonGetter(goog.ui.ImagelessButtonRenderer);
  49. /**
  50. * Default CSS class to be applied to the root element of components rendered
  51. * by this renderer.
  52. * @type {string}
  53. */
  54. goog.ui.ImagelessButtonRenderer.CSS_CLASS =
  55. goog.getCssName('goog-imageless-button');
  56. /**
  57. * Returns the button's contents wrapped in the following DOM structure:
  58. *
  59. * <div class="goog-inline-block goog-imageless-button">
  60. * <div class="goog-inline-block goog-imageless-button-outer-box">
  61. * <div class="goog-imageless-button-inner-box">
  62. * <div class="goog-imageless-button-pos-box">
  63. * <div class="goog-imageless-button-top-shadow">&nbsp;</div>
  64. * <div class="goog-imageless-button-content">Contents...</div>
  65. * </div>
  66. * </div>
  67. * </div>
  68. * </div>
  69. * @override
  70. */
  71. goog.ui.ImagelessButtonRenderer.prototype.createDom;
  72. /** @override */
  73. goog.ui.ImagelessButtonRenderer.prototype.getContentElement = function(
  74. element) {
  75. return /** @type {Element} */ (
  76. element && element.firstChild && element.firstChild.firstChild &&
  77. element.firstChild.firstChild.firstChild.lastChild);
  78. };
  79. /**
  80. * Takes a text caption or existing DOM structure, and returns the content
  81. * wrapped in a pseudo-rounded-corner box. Creates the following DOM structure:
  82. *
  83. * <div class="goog-inline-block goog-imageless-button-outer-box">
  84. * <div class="goog-inline-block goog-imageless-button-inner-box">
  85. * <div class="goog-imageless-button-pos">
  86. * <div class="goog-imageless-button-top-shadow">&nbsp;</div>
  87. * <div class="goog-imageless-button-content">Contents...</div>
  88. * </div>
  89. * </div>
  90. * </div>
  91. *
  92. * Used by both {@link #createDom} and {@link #decorate}. To be overridden
  93. * by subclasses.
  94. * @param {goog.ui.ControlContent} content Text caption or DOM structure to wrap
  95. * in a box.
  96. * @param {goog.dom.DomHelper} dom DOM helper, used for document interaction.
  97. * @return {Element} Pseudo-rounded-corner box containing the content.
  98. * @override
  99. */
  100. goog.ui.ImagelessButtonRenderer.prototype.createButton = function(
  101. content, dom) {
  102. var baseClass = this.getCssClass();
  103. var inlineBlock = goog.ui.INLINE_BLOCK_CLASSNAME + ' ';
  104. return dom.createDom(
  105. goog.dom.TagName.DIV,
  106. inlineBlock + goog.getCssName(baseClass, 'outer-box'),
  107. dom.createDom(
  108. goog.dom.TagName.DIV,
  109. inlineBlock + goog.getCssName(baseClass, 'inner-box'),
  110. dom.createDom(
  111. goog.dom.TagName.DIV, goog.getCssName(baseClass, 'pos'),
  112. dom.createDom(
  113. goog.dom.TagName.DIV,
  114. goog.getCssName(baseClass, 'top-shadow'), '\u00A0'),
  115. dom.createDom(
  116. goog.dom.TagName.DIV, goog.getCssName(baseClass, 'content'),
  117. content))));
  118. };
  119. /**
  120. * Check if the button's element has a box structure.
  121. * @param {goog.ui.Button} button Button instance whose structure is being
  122. * checked.
  123. * @param {Element} element Element of the button.
  124. * @return {boolean} Whether the element has a box structure.
  125. * @protected
  126. * @override
  127. */
  128. goog.ui.ImagelessButtonRenderer.prototype.hasBoxStructure = function(
  129. button, element) {
  130. var outer = button.getDomHelper().getFirstElementChild(element);
  131. var outerClassName = goog.getCssName(this.getCssClass(), 'outer-box');
  132. if (outer && goog.dom.classlist.contains(outer, outerClassName)) {
  133. var inner = button.getDomHelper().getFirstElementChild(outer);
  134. var innerClassName = goog.getCssName(this.getCssClass(), 'inner-box');
  135. if (inner && goog.dom.classlist.contains(inner, innerClassName)) {
  136. var pos = button.getDomHelper().getFirstElementChild(inner);
  137. var posClassName = goog.getCssName(this.getCssClass(), 'pos');
  138. if (pos && goog.dom.classlist.contains(pos, posClassName)) {
  139. var shadow = button.getDomHelper().getFirstElementChild(pos);
  140. var shadowClassName = goog.getCssName(this.getCssClass(), 'top-shadow');
  141. if (shadow && goog.dom.classlist.contains(shadow, shadowClassName)) {
  142. var content = button.getDomHelper().getNextElementSibling(shadow);
  143. var contentClassName = goog.getCssName(this.getCssClass(), 'content');
  144. if (content &&
  145. goog.dom.classlist.contains(content, contentClassName)) {
  146. // We have a proper box structure.
  147. return true;
  148. }
  149. }
  150. }
  151. }
  152. }
  153. return false;
  154. };
  155. /**
  156. * Returns the CSS class to be applied to the root element of components
  157. * rendered using this renderer.
  158. * @return {string} Renderer-specific CSS class.
  159. * @override
  160. */
  161. goog.ui.ImagelessButtonRenderer.prototype.getCssClass = function() {
  162. return goog.ui.ImagelessButtonRenderer.CSS_CLASS;
  163. };
  164. // Register a decorator factory function for goog.ui.ImagelessButtonRenderer.
  165. goog.ui.registry.setDecoratorByClassName(
  166. goog.ui.ImagelessButtonRenderer.CSS_CLASS, function() {
  167. return new goog.ui.Button(
  168. null, goog.ui.ImagelessButtonRenderer.getInstance());
  169. });
  170. // Register a decorator factory function for toggle buttons using the
  171. // goog.ui.ImagelessButtonRenderer.
  172. goog.ui.registry.setDecoratorByClassName(
  173. goog.getCssName('goog-imageless-toggle-button'), function() {
  174. var button = new goog.ui.Button(
  175. null, goog.ui.ImagelessButtonRenderer.getInstance());
  176. button.setSupportedState(goog.ui.Component.State.CHECKED, true);
  177. return button;
  178. });