checkboxrenderer.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright 2011 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 Default renderer for {@link goog.ui.Checkbox}s.
  16. *
  17. */
  18. goog.provide('goog.ui.CheckboxRenderer');
  19. goog.require('goog.a11y.aria');
  20. goog.require('goog.a11y.aria.Role');
  21. goog.require('goog.a11y.aria.State');
  22. goog.require('goog.array');
  23. goog.require('goog.asserts');
  24. goog.require('goog.dom.TagName');
  25. goog.require('goog.dom.classlist');
  26. goog.require('goog.object');
  27. goog.require('goog.ui.ControlRenderer');
  28. /**
  29. * Default renderer for {@link goog.ui.Checkbox}s. Extends the superclass
  30. * to support checkbox states:
  31. * @constructor
  32. * @extends {goog.ui.ControlRenderer}
  33. */
  34. goog.ui.CheckboxRenderer = function() {
  35. goog.ui.CheckboxRenderer.base(this, 'constructor');
  36. };
  37. goog.inherits(goog.ui.CheckboxRenderer, goog.ui.ControlRenderer);
  38. goog.addSingletonGetter(goog.ui.CheckboxRenderer);
  39. /**
  40. * Default CSS class to be applied to the root element of components rendered
  41. * by this renderer.
  42. * @type {string}
  43. */
  44. goog.ui.CheckboxRenderer.CSS_CLASS = goog.getCssName('goog-checkbox');
  45. /** @override */
  46. goog.ui.CheckboxRenderer.prototype.createDom = function(checkbox) {
  47. var element = checkbox.getDomHelper().createDom(
  48. goog.dom.TagName.SPAN, this.getClassNames(checkbox).join(' '));
  49. var state = checkbox.getChecked();
  50. this.setCheckboxState(element, state);
  51. return element;
  52. };
  53. /** @override */
  54. goog.ui.CheckboxRenderer.prototype.decorate = function(checkbox, element) {
  55. // The superclass implementation takes care of common attributes; we only
  56. // need to set the checkbox state.
  57. element = goog.ui.CheckboxRenderer.base(this, 'decorate', checkbox, element);
  58. goog.asserts.assert(element);
  59. var classes = goog.dom.classlist.get(element);
  60. // Update the checked state of the element based on its css classNames
  61. // with the following order: undetermined -> checked -> unchecked.
  62. var checked =
  63. /** @suppress {missingRequire} */ (goog.ui.Checkbox.State.UNCHECKED);
  64. if (goog.array.contains(
  65. classes, this.getClassForCheckboxState(
  66. /** @suppress {missingRequire} */
  67. goog.ui.Checkbox.State.UNDETERMINED))) {
  68. checked =
  69. (/** @suppress {missingRequire} */
  70. goog.ui.Checkbox.State.UNDETERMINED);
  71. } else if (
  72. goog.array.contains(
  73. classes, this.getClassForCheckboxState(
  74. /** @suppress {missingRequire} */ goog.ui.Checkbox.State
  75. .CHECKED))) {
  76. checked = /** @suppress {missingRequire} */ goog.ui.Checkbox.State.CHECKED;
  77. } else if (goog.array.contains(classes,
  78. this.getClassForCheckboxState(/** @suppress {missingRequire} */
  79. goog.ui.Checkbox.State.UNCHECKED))) {
  80. checked =
  81. (/** @suppress {missingRequire} */
  82. goog.ui.Checkbox.State.UNCHECKED);
  83. }
  84. checkbox.setCheckedInternal(checked);
  85. goog.asserts.assert(element, 'The element cannot be null.');
  86. goog.a11y.aria.setState(
  87. element, goog.a11y.aria.State.CHECKED,
  88. this.ariaStateFromCheckState_(checked));
  89. return element;
  90. };
  91. /**
  92. * Returns the ARIA role to be applied to checkboxes.
  93. * @return {goog.a11y.aria.Role} ARIA role.
  94. * @override
  95. */
  96. goog.ui.CheckboxRenderer.prototype.getAriaRole = function() {
  97. return goog.a11y.aria.Role.CHECKBOX;
  98. };
  99. /**
  100. * Updates the appearance of the control in response to a checkbox state
  101. * change.
  102. * @param {Element} element Checkbox element.
  103. * @param {goog.ui.Checkbox.State} state Updated checkbox state.
  104. */
  105. goog.ui.CheckboxRenderer.prototype.setCheckboxState = function(element, state) {
  106. if (element) {
  107. goog.asserts.assert(element);
  108. var classToAdd = this.getClassForCheckboxState(state);
  109. goog.asserts.assert(classToAdd);
  110. goog.asserts.assert(element);
  111. if (goog.dom.classlist.contains(element, classToAdd)) {
  112. return;
  113. }
  114. goog.object.forEach(
  115. /** @suppress {missingRequire} */ goog.ui.Checkbox.State,
  116. function(state) {
  117. var className = this.getClassForCheckboxState(state);
  118. goog.asserts.assert(element);
  119. goog.dom.classlist.enable(
  120. element, className, className == classToAdd);
  121. },
  122. this);
  123. goog.a11y.aria.setState(
  124. element, goog.a11y.aria.State.CHECKED,
  125. this.ariaStateFromCheckState_(state));
  126. }
  127. };
  128. /**
  129. * Gets the checkbox's ARIA (accessibility) state from its checked state.
  130. * @param {goog.ui.Checkbox.State} state Checkbox state.
  131. * @return {string} The value of goog.a11y.aria.state.CHECKED. Either 'true',
  132. * 'false', or 'mixed'.
  133. * @private
  134. */
  135. goog.ui.CheckboxRenderer.prototype.ariaStateFromCheckState_ = function(state) {
  136. if (state ==
  137. /** @suppress {missingRequire} */ goog.ui.Checkbox.State.UNDETERMINED) {
  138. return 'mixed';
  139. } else if (
  140. state ==
  141. /** @suppress {missingRequire} */ goog.ui.Checkbox.State.CHECKED) {
  142. return 'true';
  143. } else {
  144. return 'false';
  145. }
  146. };
  147. /** @override */
  148. goog.ui.CheckboxRenderer.prototype.getCssClass = function() {
  149. return goog.ui.CheckboxRenderer.CSS_CLASS;
  150. };
  151. /**
  152. * Takes a single {@link goog.ui.Checkbox.State}, and returns the
  153. * corresponding CSS class name.
  154. * @param {goog.ui.Checkbox.State} state Checkbox state.
  155. * @return {string} CSS class representing the given state.
  156. * @protected
  157. * @suppress {missingRequire} goog.ui.Checkbox
  158. */
  159. goog.ui.CheckboxRenderer.prototype.getClassForCheckboxState = function(state) {
  160. var baseClass = this.getStructuralCssClass();
  161. if (state == goog.ui.Checkbox.State.CHECKED) {
  162. return goog.getCssName(baseClass, 'checked');
  163. } else if (state == goog.ui.Checkbox.State.UNCHECKED) {
  164. return goog.getCssName(baseClass, 'unchecked');
  165. } else if (state == goog.ui.Checkbox.State.UNDETERMINED) {
  166. return goog.getCssName(baseClass, 'undetermined');
  167. }
  168. throw Error('Invalid checkbox state: ' + state);
  169. };