nativebuttonrenderer.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 Native browser button renderer for {@link goog.ui.Button}s.
  16. *
  17. * @author attila@google.com (Attila Bodis)
  18. */
  19. goog.provide('goog.ui.NativeButtonRenderer');
  20. goog.require('goog.asserts');
  21. goog.require('goog.dom.InputType');
  22. goog.require('goog.dom.TagName');
  23. goog.require('goog.dom.classlist');
  24. goog.require('goog.events.EventType');
  25. goog.require('goog.ui.ButtonRenderer');
  26. goog.require('goog.ui.Component');
  27. /**
  28. * Renderer for {@link goog.ui.Button}s. Renders and decorates native HTML
  29. * button elements. Since native HTML buttons have built-in support for many
  30. * features, overrides many expensive (and redundant) superclass methods to
  31. * be no-ops.
  32. * @constructor
  33. * @extends {goog.ui.ButtonRenderer}
  34. */
  35. goog.ui.NativeButtonRenderer = function() {
  36. goog.ui.ButtonRenderer.call(this);
  37. };
  38. goog.inherits(goog.ui.NativeButtonRenderer, goog.ui.ButtonRenderer);
  39. goog.addSingletonGetter(goog.ui.NativeButtonRenderer);
  40. /** @override */
  41. goog.ui.NativeButtonRenderer.prototype.getAriaRole = function() {
  42. // Native buttons don't need ARIA roles to be recognized by screen readers.
  43. return undefined;
  44. };
  45. /**
  46. * Returns the button's contents wrapped in a native HTML button element. Sets
  47. * the button's disabled attribute as needed.
  48. * @param {goog.ui.Control} button Button to render.
  49. * @return {Element} Root element for the button (a native HTML button element).
  50. * @override
  51. */
  52. goog.ui.NativeButtonRenderer.prototype.createDom = function(button) {
  53. this.setUpNativeButton_(button);
  54. return button.getDomHelper().createDom(
  55. goog.dom.TagName.BUTTON, {
  56. 'class': this.getClassNames(button).join(' '),
  57. 'disabled': !button.isEnabled(),
  58. 'title': button.getTooltip() || '',
  59. 'value': button.getValue() || ''
  60. },
  61. button.getCaption() || '');
  62. };
  63. /**
  64. * Overrides {@link goog.ui.ButtonRenderer#canDecorate} by returning true only
  65. * if the element is an HTML button.
  66. * @param {Element} element Element to decorate.
  67. * @return {boolean} Whether the renderer can decorate the element.
  68. * @override
  69. */
  70. goog.ui.NativeButtonRenderer.prototype.canDecorate = function(element) {
  71. return element.tagName == goog.dom.TagName.BUTTON ||
  72. (element.tagName == goog.dom.TagName.INPUT &&
  73. (element.type == goog.dom.InputType.BUTTON ||
  74. element.type == goog.dom.InputType.SUBMIT ||
  75. element.type == goog.dom.InputType.RESET));
  76. };
  77. /** @override */
  78. goog.ui.NativeButtonRenderer.prototype.decorate = function(button, element) {
  79. this.setUpNativeButton_(button);
  80. if (element.disabled) {
  81. // Add the marker class for the DISABLED state before letting the superclass
  82. // implementation decorate the element, so its state will be correct.
  83. var disabledClassName = goog.asserts.assertString(
  84. this.getClassForState(goog.ui.Component.State.DISABLED));
  85. goog.dom.classlist.add(element, disabledClassName);
  86. }
  87. return goog.ui.NativeButtonRenderer.superClass_.decorate.call(
  88. this, button, element);
  89. };
  90. /**
  91. * Native buttons natively support BiDi and keyboard focus.
  92. * @suppress {visibility} getHandler and performActionInternal
  93. * @override
  94. */
  95. goog.ui.NativeButtonRenderer.prototype.initializeDom = function(button) {
  96. // WARNING: This is a hack, and it is only applicable to native buttons,
  97. // which are special because they do natively what most goog.ui.Controls
  98. // do programmatically. Do not use your renderer's initializeDom method
  99. // to hook up event handlers!
  100. button.getHandler().listen(
  101. button.getElement(), goog.events.EventType.CLICK,
  102. button.performActionInternal);
  103. };
  104. /**
  105. * @override
  106. * Native buttons don't support text selection.
  107. */
  108. goog.ui.NativeButtonRenderer.prototype.setAllowTextSelection =
  109. goog.nullFunction;
  110. /**
  111. * @override
  112. * Native buttons natively support right-to-left rendering.
  113. */
  114. goog.ui.NativeButtonRenderer.prototype.setRightToLeft = goog.nullFunction;
  115. /**
  116. * @override
  117. * Native buttons are always focusable as long as they are enabled.
  118. */
  119. goog.ui.NativeButtonRenderer.prototype.isFocusable = function(button) {
  120. return button.isEnabled();
  121. };
  122. /**
  123. * @override
  124. * Native buttons natively support keyboard focus.
  125. */
  126. goog.ui.NativeButtonRenderer.prototype.setFocusable = goog.nullFunction;
  127. /**
  128. * @override
  129. * Native buttons also expose the DISABLED state in the HTML button's
  130. * {@code disabled} attribute.
  131. */
  132. goog.ui.NativeButtonRenderer.prototype.setState = function(
  133. button, state, enable) {
  134. goog.ui.NativeButtonRenderer.superClass_.setState.call(
  135. this, button, state, enable);
  136. var element = button.getElement();
  137. if (element && state == goog.ui.Component.State.DISABLED) {
  138. element.disabled = enable;
  139. }
  140. };
  141. /**
  142. * @override
  143. * Native buttons store their value in the HTML button's {@code value}
  144. * attribute.
  145. */
  146. goog.ui.NativeButtonRenderer.prototype.getValue = function(element) {
  147. // TODO(attila): Make this work on IE! This never worked...
  148. // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
  149. // for a description of the problem.
  150. return element.value;
  151. };
  152. /**
  153. * @override
  154. * Native buttons also expose their value in the HTML button's {@code value}
  155. * attribute.
  156. */
  157. goog.ui.NativeButtonRenderer.prototype.setValue = function(element, value) {
  158. if (element) {
  159. // TODO(attila): Make this work on IE! This never worked...
  160. // See http://www.fourmilab.ch/fourmilog/archives/2007-03/000824.html
  161. // for a description of the problem.
  162. element.value = value;
  163. }
  164. };
  165. /**
  166. * @override
  167. * Native buttons don't need ARIA states to support accessibility, so this is
  168. * a no-op.
  169. */
  170. goog.ui.NativeButtonRenderer.prototype.updateAriaState = goog.nullFunction;
  171. /**
  172. * Sets up the button control such that it doesn't waste time adding
  173. * functionality that is already natively supported by native browser
  174. * buttons.
  175. * @param {goog.ui.Control} button Button control to configure.
  176. * @private
  177. */
  178. goog.ui.NativeButtonRenderer.prototype.setUpNativeButton_ = function(button) {
  179. button.setHandleMouseEvents(false);
  180. button.setAutoStates(goog.ui.Component.State.ALL, false);
  181. button.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  182. };