diff options
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/ui/controlrenderer.js')
-rw-r--r-- | contexts/data/lib/closure-library/closure/goog/ui/controlrenderer.js | 844 |
1 files changed, 0 insertions, 844 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/ui/controlrenderer.js b/contexts/data/lib/closure-library/closure/goog/ui/controlrenderer.js deleted file mode 100644 index c88eac1..0000000 --- a/contexts/data/lib/closure-library/closure/goog/ui/controlrenderer.js +++ /dev/null @@ -1,844 +0,0 @@ -// Copyright 2008 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Base class for control renderers. - * TODO(attila): If the renderer framework works well, pull it into Component. - * - * @author attila@google.com (Attila Bodis) - */ - -goog.provide('goog.ui.ControlRenderer'); - -goog.require('goog.array'); -goog.require('goog.dom'); -goog.require('goog.dom.a11y'); -goog.require('goog.dom.a11y.State'); -goog.require('goog.dom.classes'); -goog.require('goog.object'); -goog.require('goog.style'); -goog.require('goog.ui.Component.State'); -goog.require('goog.ui.ControlContent'); -goog.require('goog.userAgent'); - - - -/** - * Default renderer for {@link goog.ui.Control}s. Can be used as-is, but - * subclasses of Control will probably want to use renderers specifically - * tailored for them by extending this class. Controls that use renderers - * delegate one or more of the following API methods to the renderer: - * <ul> - * <li>{@code createDom} - renders the DOM for the component - * <li>{@code canDecorate} - determines whether an element can be decorated - * by the component - * <li>{@code decorate} - decorates an existing element with the component - * <li>{@code setState} - updates the appearance of the component based on - * its state - * <li>{@code getContent} - returns the component's content - * <li>{@code setContent} - sets the component's content - * </ul> - * Controls are stateful; renderers, on the other hand, should be stateless and - * reusable. - * @constructor - */ -goog.ui.ControlRenderer = function() { -}; -goog.addSingletonGetter(goog.ui.ControlRenderer); - - -/** - * Constructs a new renderer and sets the CSS class that the renderer will use - * as the base CSS class to apply to all elements rendered by that renderer. - * An example to use this function using a color palette: - * - * <pre> - * var myCustomRenderer = goog.ui.ControlRenderer.getCustomRenderer( - * goog.ui.PaletteRenderer, 'my-special-palette'); - * var newColorPalette = new goog.ui.ColorPalette( - * colors, myCustomRenderer, opt_domHelper); - * </pre> - * - * Your CSS can look like this now: - * <pre> - * .my-special-palette { } - * .my-special-palette-table { } - * .my-special-palette-cell { } - * etc. - * </pre> - * - * <em>instead</em> of - * <pre> - * .CSS_MY_SPECIAL_PALETTE .goog-palette { } - * .CSS_MY_SPECIAL_PALETTE .goog-palette-table { } - * .CSS_MY_SPECIAL_PALETTE .goog-palette-cell { } - * etc. - * </pre> - * - * You would want to use this functionality when you want an instance of a - * component to have specific styles different than the other components of the - * same type in your application. This avoids using descendant selectors to - * apply the specific styles to this component. - * - * @param {Function} ctor The constructor of the renderer you are trying to - * create. - * @param {string} cssClassName The name of the CSS class for this renderer. - * @return {goog.ui.ControlRenderer} An instance of the desired renderer with - * its getCssClass() method overridden to return the supplied custom CSS - * class name. - */ -goog.ui.ControlRenderer.getCustomRenderer = function(ctor, cssClassName) { - var renderer = new ctor(); - - /** - * Returns the CSS class to be applied to the root element of components - * rendered using this renderer. - * @return {string} Renderer-specific CSS class. - */ - renderer.getCssClass = function() { - return cssClassName; - }; - - return renderer; -}; - - -/** - * Default CSS class to be applied to the root element of components rendered - * by this renderer. - * @type {string} - */ -goog.ui.ControlRenderer.CSS_CLASS = goog.getCssName('goog-control'); - - -/** - * Array of arrays of CSS classes that we want composite classes added and - * removed for in IE6 and lower as a workaround for lack of multi-class CSS - * selector support. - * - * Subclasses that have accompanying CSS requiring this workaround should define - * their own static IE6_CLASS_COMBINATIONS constant and override - * getIe6ClassCombinations to return it. - * - * For example, if your stylesheet uses the selector .button.collapse-left - * (and is compiled to .button_collapse-left for the IE6 version of the - * stylesheet,) you should include ['button', 'collapse-left'] in this array - * and the class button_collapse-left will be applied to the root element - * whenever both button and collapse-left are applied individually. - * - * Members of each class name combination will be joined with underscores in the - * order that they're defined in the array. You should alphabetize them (for - * compatibility with the CSS compiler) unless you are doing something special. - * @type {Array.<Array.<string>>} - */ -goog.ui.ControlRenderer.IE6_CLASS_COMBINATIONS = []; - - -/** - * Map of component states to corresponding ARIA states. Since the mapping of - * component states to ARIA states is neither component- nor renderer-specific, - * this is a static property of the renderer class, and is initialized on first - * use. - * @type {Object} - * @private - */ -goog.ui.ControlRenderer.ARIA_STATE_MAP_; - - -/** - * Returns the ARIA role to be applied to the control. - * See http://wiki/Main/ARIA for more info. - * @return {goog.dom.a11y.Role|undefined} ARIA role. - */ -goog.ui.ControlRenderer.prototype.getAriaRole = function() { - // By default, the ARIA role is unspecified. - return undefined; -}; - - -/** - * Returns the control's contents wrapped in a DIV, with the renderer's own - * CSS class and additional state-specific classes applied to it. - * @param {goog.ui.Control} control Control to render. - * @return {Element} Root element for the control. - */ -goog.ui.ControlRenderer.prototype.createDom = function(control) { - // Create and return DIV wrapping contents. - var element = control.getDomHelper().createDom( - 'div', this.getClassNames(control).join(' '), control.getContent()); - - this.setAriaStates(control, element); - return element; -}; - - -/** - * Takes the control's root element and returns the parent element of the - * control's contents. Since by default controls are rendered as a single - * DIV, the default implementation returns the element itself. Subclasses - * with more complex DOM structures must override this method as needed. - * @param {Element} element Root element of the control whose content element - * is to be returned. - * @return {Element} The control's content element. - */ -goog.ui.ControlRenderer.prototype.getContentElement = function(element) { - return element; -}; - - -/** - * Updates the control's DOM by adding or removing the specified class name - * to/from its root element. May add additional combined classes as needed in - * IE6 and lower. Because of this, subclasses should use this method when - * modifying class names on the control's root element. - * @param {goog.ui.Control|Element} control Control instance (or root element) - * to be updated. - * @param {string} className CSS class name to add or remove. - * @param {boolean} enable Whether to add or remove the class name. - */ -goog.ui.ControlRenderer.prototype.enableClassName = function(control, - className, enable) { - var element = (/** @type {Element} */ - control.getElement ? control.getElement() : control); - if (element) { - // For IE6, we need to enable any combined classes involving this class - // as well. - if (goog.userAgent.IE && !goog.userAgent.isVersion('7')) { - var combinedClasses = this.getAppliedCombinedClassNames_( - goog.dom.classes.get(element), className); - combinedClasses.push(className); - var f = enable ? goog.dom.classes.add : goog.dom.classes.remove; - goog.partial(f, element).apply(null, combinedClasses); - } else { - goog.dom.classes.enable(element, className, enable); - } - } -}; - - -/** - * Updates the control's DOM by adding or removing the specified extra class - * name to/from its element. - * @param {goog.ui.Control} control Control to be updated. - * @param {string} className CSS class name to add or remove. - * @param {boolean} enable Whether to add or remove the class name. - */ -goog.ui.ControlRenderer.prototype.enableExtraClassName = function(control, - className, enable) { - // The base class implementation is trivial; subclasses should override as - // needed. - this.enableClassName(control, className, enable); -}; - - -/** - * Returns true if this renderer can decorate the element, false otherwise. - * The default implementation always returns true. - * @param {Element} element Element to decorate. - * @return {boolean} Whether the renderer can decorate the element. - */ -goog.ui.ControlRenderer.prototype.canDecorate = function(element) { - return true; -}; - - -/** - * Default implementation of {@code decorate} for {@link goog.ui.Control}s. - * Initializes the control's ID, content, and state based on the ID of the - * element, its child nodes, and its CSS classes, respectively. Returns the - * element. - * @param {goog.ui.Control} control Control instance to decorate the element. - * @param {Element} element Element to decorate. - * @return {Element} Decorated element. - * @suppress {visibility} setContentInternal and setStateInternal - */ -goog.ui.ControlRenderer.prototype.decorate = function(control, element) { - // Set the control's ID to the decorated element's DOM ID, if any. - if (element.id) { - control.setId(element.id); - } - - // Set the control's content to the decorated element's content. - var contentElem = this.getContentElement(element); - if (contentElem && contentElem.firstChild) { - control.setContentInternal(contentElem.firstChild.nextSibling ? - goog.array.clone(contentElem.childNodes) : contentElem.firstChild); - } else { - control.setContentInternal(null); - } - - // Initialize the control's state based on the decorated element's CSS class. - // This implementation is optimized to minimize object allocations, string - // comparisons, and DOM access. - var state = 0x00; - var rendererClassName = this.getCssClass(); - var structuralClassName = this.getStructuralCssClass(); - var hasRendererClassName = false; - var hasStructuralClassName = false; - var hasCombinedClassName = false; - var classNames = goog.dom.classes.get(element); - goog.array.forEach(classNames, function(className) { - if (!hasRendererClassName && className == rendererClassName) { - hasRendererClassName = true; - if (structuralClassName == rendererClassName) { - hasStructuralClassName = true; - } - } else if (!hasStructuralClassName && className == structuralClassName) { - hasStructuralClassName = true; - } else { - state |= this.getStateFromClass(className); - } - }, this); - control.setStateInternal(state); - - // Make sure the element has the renderer's CSS classes applied, as well as - // any extra class names set on the control. - if (!hasRendererClassName) { - classNames.push(rendererClassName); - if (structuralClassName == rendererClassName) { - hasStructuralClassName = true; - } - } - if (!hasStructuralClassName) { - classNames.push(structuralClassName); - } - var extraClassNames = control.getExtraClassNames(); - if (extraClassNames) { - classNames.push.apply(classNames, extraClassNames); - } - - // For IE6, rewrite all classes on the decorated element if any combined - // classes apply. - if (goog.userAgent.IE && !goog.userAgent.isVersion('7')) { - var combinedClasses = this.getAppliedCombinedClassNames_( - classNames); - if (combinedClasses.length > 0) { - classNames.push.apply(classNames, combinedClasses); - hasCombinedClassName = true; - } - } - - // Only write to the DOM if new class names had to be added to the element. - if (!hasRendererClassName || !hasStructuralClassName || - extraClassNames || hasCombinedClassName) { - goog.dom.classes.set(element, classNames.join(' ')); - } - - this.setAriaStates(control, element); - return element; -}; - - -/** - * Initializes the control's DOM by configuring properties that can only be set - * after the DOM has entered the document. This implementation sets up BiDi - * and keyboard focus. Called from {@link goog.ui.Control#enterDocument}. - * @param {goog.ui.Control} control Control whose DOM is to be initialized - * as it enters the document. - */ -goog.ui.ControlRenderer.prototype.initializeDom = function(control) { - // Initialize render direction (BiDi). We optimize the left-to-right render - // direction by assuming that elements are left-to-right by default, and only - // updating their styling if they are explicitly set to right-to-left. - if (control.isRightToLeft()) { - this.setRightToLeft(control.getElement(), true); - } - - // Initialize keyboard focusability (tab index). We assume that components - // aren't focusable by default (i.e have no tab index), and only touch the - // DOM if the component is focusable, enabled, and visible, and therefore - // needs a tab index. - if (control.isEnabled()) { - this.setFocusable(control, control.isVisible()); - } -}; - - -/** - * Sets the element's ARIA role. - * @param {Element} element Element to update. - * @param {?goog.dom.a11y.Role=} opt_preferredRole The preferred ARIA role. - */ -goog.ui.ControlRenderer.prototype.setAriaRole = function(element, - opt_preferredRole) { - var ariaRole = opt_preferredRole || this.getAriaRole(); - if (ariaRole) { - goog.dom.a11y.setRole(element, ariaRole); - } -}; - - -/** - * Sets the element's ARIA states. An element does not need an ARIA role in - * order to have an ARIA state. Only states which are initialized to be true - * will be set. - * @param {!goog.ui.Control} control Control whose ARIA state will be updated. - * @param {!Element} element Element whose ARIA state is to be updated. - */ -goog.ui.ControlRenderer.prototype.setAriaStates = function(control, element) { - goog.asserts.assert(control); - goog.asserts.assert(element); - if (!control.isEnabled()) { - this.updateAriaState(element, goog.ui.Component.State.DISABLED, - true); - } - if (control.isSelected()) { - this.updateAriaState(element, goog.ui.Component.State.SELECTED, - true); - } - if (control.isSupportedState(goog.ui.Component.State.CHECKED)) { - this.updateAriaState(element, goog.ui.Component.State.CHECKED, - control.isChecked()); - } - if (control.isSupportedState(goog.ui.Component.State.OPENED)) { - this.updateAriaState(element, goog.ui.Component.State.OPENED, - control.isOpen()); - } -}; - - -/** - * Allows or disallows text selection within the control's DOM. - * @param {Element} element The control's root element. - * @param {boolean} allow Whether the element should allow text selection. - */ -goog.ui.ControlRenderer.prototype.setAllowTextSelection = function(element, - allow) { - // On all browsers other than IE and Opera, it isn't necessary to recursively - // apply unselectable styling to the element's children. - goog.style.setUnselectable(element, !allow, - !goog.userAgent.IE && !goog.userAgent.OPERA); -}; - - -/** - * Applies special styling to/from the control's element if it is rendered - * right-to-left, and removes it if it is rendered left-to-right. - * @param {Element} element The control's root element. - * @param {boolean} rightToLeft Whether the component is rendered - * right-to-left. - */ -goog.ui.ControlRenderer.prototype.setRightToLeft = function(element, - rightToLeft) { - this.enableClassName(element, - goog.getCssName(this.getStructuralCssClass(), 'rtl'), rightToLeft); -}; - - -/** - * Returns true if the control's key event target supports keyboard focus - * (based on its {@code tabIndex} attribute), false otherwise. - * @param {goog.ui.Control} control Control whose key event target is to be - * checked. - * @return {boolean} Whether the control's key event target is focusable. - */ -goog.ui.ControlRenderer.prototype.isFocusable = function(control) { - var keyTarget; - if (control.isSupportedState(goog.ui.Component.State.FOCUSED) && - (keyTarget = control.getKeyEventTarget())) { - return goog.dom.isFocusableTabIndex(keyTarget); - } - return false; -}; - - -/** - * Updates the control's key event target to make it focusable or non-focusable - * via its {@code tabIndex} attribute. Does nothing if the control doesn't - * support the {@code FOCUSED} state, or if it has no key event target. - * @param {goog.ui.Control} control Control whose key event target is to be - * updated. - * @param {boolean} focusable Whether to enable keyboard focus support on the - * control's key event target. - */ -goog.ui.ControlRenderer.prototype.setFocusable = function(control, focusable) { - var keyTarget; - if (control.isSupportedState(goog.ui.Component.State.FOCUSED) && - (keyTarget = control.getKeyEventTarget())) { - if (!focusable && control.isFocused()) { - // Blur before hiding. Note that IE calls onblur handlers asynchronously. - try { - keyTarget.blur(); - } catch (e) { - // TODO(user|user): Find out why this fails on IE. - } - // The blur event dispatched by the key event target element when blur() - // was called on it should have been handled by the control's handleBlur() - // method, so at this point the control should no longer be focused. - // However, blur events are unreliable on IE and FF3, so if at this point - // the control is still focused, we trigger its handleBlur() method - // programmatically. - if (control.isFocused()) { - control.handleBlur(null); - } - } - // Don't overwrite existing tab index values unless needed. - if (goog.dom.isFocusableTabIndex(keyTarget) != focusable) { - goog.dom.setFocusableTabIndex(keyTarget, focusable); - } - } -}; - - -/** - * Shows or hides the element. - * @param {Element} element Element to update. - * @param {boolean} visible Whether to show the element. - */ -goog.ui.ControlRenderer.prototype.setVisible = function(element, visible) { - // The base class implementation is trivial; subclasses should override as - // needed. It should be possible to do animated reveals, for example. - goog.style.showElement(element, visible); -}; - - -/** - * Updates the appearance of the control in response to a state change. - * @param {goog.ui.Control} control Control instance to update. - * @param {goog.ui.Component.State} state State to enable or disable. - * @param {boolean} enable Whether the control is entering or exiting the state. - */ -goog.ui.ControlRenderer.prototype.setState = function(control, state, enable) { - var element = control.getElement(); - if (element) { - var className = this.getClassForState(state); - if (className) { - this.enableClassName(control, className, enable); - } - this.updateAriaState(element, state, enable); - } -}; - - -/** - * Updates the element's ARIA (accessibility) state. - * @param {Element} element Element whose ARIA state is to be updated. - * @param {goog.ui.Component.State} state Component state being enabled or - * disabled. - * @param {boolean} enable Whether the state is being enabled or disabled. - * @protected - */ -goog.ui.ControlRenderer.prototype.updateAriaState = function(element, state, - enable) { - // Ensure the ARIA state map exists. - if (!goog.ui.ControlRenderer.ARIA_STATE_MAP_) { - goog.ui.ControlRenderer.ARIA_STATE_MAP_ = goog.object.create( - goog.ui.Component.State.DISABLED, goog.dom.a11y.State.DISABLED, - goog.ui.Component.State.SELECTED, goog.dom.a11y.State.SELECTED, - goog.ui.Component.State.CHECKED, goog.dom.a11y.State.CHECKED, - goog.ui.Component.State.OPENED, goog.dom.a11y.State.EXPANDED); - } - var ariaState = goog.ui.ControlRenderer.ARIA_STATE_MAP_[state]; - if (ariaState) { - goog.dom.a11y.setState(element, ariaState, enable); - } -}; - - -/** - * Takes a control's root element, and sets its content to the given text - * caption or DOM structure. The default implementation replaces the children - * of the given element. Renderers that create more complex DOM structures - * must override this method accordingly. - * @param {Element} element The control's root element. - * @param {goog.ui.ControlContent} content Text caption or DOM structure to be - * set as the control's content. The DOM nodes will not be cloned, they - * will only moved under the content element of the control. - */ -goog.ui.ControlRenderer.prototype.setContent = function(element, content) { - var contentElem = this.getContentElement(element); - if (contentElem) { - goog.dom.removeChildren(contentElem); - if (content) { - if (goog.isString(content)) { - goog.dom.setTextContent(contentElem, content); - } else { - var childHandler = function(child) { - if (child) { - var doc = goog.dom.getOwnerDocument(contentElem); - contentElem.appendChild(goog.isString(child) ? - doc.createTextNode(child) : child); - } - }; - if (goog.isArray(content)) { - // Array of nodes. - goog.array.forEach(content, childHandler); - } else if (goog.isArrayLike(content) && !('nodeType' in content)) { - // NodeList. The second condition filters out TextNode which also has - // length attribute but is not array like. The nodes have to be cloned - // because childHandler removes them from the list during iteration. - goog.array.forEach(goog.array.clone(/** @type {NodeList} */(content)), - childHandler); - } else { - // Node or string. - childHandler(content); - } - } - } - } -}; - - -/** - * Returns the element within the component's DOM that should receive keyboard - * focus (null if none). The default implementation returns the control's root - * element. - * @param {goog.ui.Control} control Control whose key event target is to be - * returned. - * @return {Element} The key event target. - */ -goog.ui.ControlRenderer.prototype.getKeyEventTarget = function(control) { - return control.getElement(); -}; - - -// CSS class name management. - - -/** - * Returns the CSS class name to be applied to the root element of all - * components rendered or decorated using this renderer. The class name - * is expected to uniquely identify the renderer class, i.e. no two - * renderer classes are expected to share the same CSS class name. - * @return {string} Renderer-specific CSS class name. - */ -goog.ui.ControlRenderer.prototype.getCssClass = function() { - return goog.ui.ControlRenderer.CSS_CLASS; -}; - - -/** - * Returns an array of combinations of classes to apply combined class names for - * in IE6 and below. See {@link IE6_CLASS_COMBINATIONS} for more detail. This - * method doesn't reference {@link IE6_CLASS_COMBINATIONS} so that it can be - * compiled out, but subclasses should return their IE6_CLASS_COMBINATIONS - * static constant instead. - * @return {Array.<Array.<string>>} Array of class name combinations. - */ -goog.ui.ControlRenderer.prototype.getIe6ClassCombinations = function() { - return []; -}; - - -/** - * Returns the name of a DOM structure-specific CSS class to be applied to the - * root element of all components rendered or decorated using this renderer. - * Unlike the class name returned by {@link #getCssClass}, the structural class - * name may be shared among different renderers that generate similar DOM - * structures. The structural class name also serves as the basis of derived - * class names used to identify and style structural elements of the control's - * DOM, as well as the basis for state-specific class names. The default - * implementation returns the same class name as {@link #getCssClass}, but - * subclasses are expected to override this method as needed. - * @return {string} DOM structure-specific CSS class name (same as the renderer- - * specific CSS class name by default). - */ -goog.ui.ControlRenderer.prototype.getStructuralCssClass = function() { - return this.getCssClass(); -}; - - -/** - * Returns all CSS class names applicable to the given control, based on its - * state. The return value is an array of strings containing - * <ol> - * <li>the renderer-specific CSS class returned by {@link #getCssClass}, - * followed by - * <li>the structural CSS class returned by {@link getStructuralCssClass} (if - * different from the renderer-specific CSS class), followed by - * <li>any state-specific classes returned by {@link #getClassNamesForState}, - * followed by - * <li>any extra classes returned by the control's {@code getExtraClassNames} - * method and - * <li>for IE6 and lower, additional combined classes from - * {@link getAppliedCombinedClassNames_}. - * </ol> - * Since all controls have at least one renderer-specific CSS class name, this - * method is guaranteed to return an array of at least one element. - * @param {goog.ui.Control} control Control whose CSS classes are to be - * returned. - * @return {Array.<string>} Array of CSS class names applicable to the control. - * @protected - */ -goog.ui.ControlRenderer.prototype.getClassNames = function(control) { - var cssClass = this.getCssClass(); - - // Start with the renderer-specific class name. - var classNames = [cssClass]; - - // Add structural class name, if different. - var structuralCssClass = this.getStructuralCssClass(); - if (structuralCssClass != cssClass) { - classNames.push(structuralCssClass); - } - - // Add state-specific class names, if any. - var classNamesForState = this.getClassNamesForState(control.getState()); - classNames.push.apply(classNames, classNamesForState); - - // Add extra class names, if any. - var extraClassNames = control.getExtraClassNames(); - if (extraClassNames) { - classNames.push.apply(classNames, extraClassNames); - } - - // Add composite classes for IE6 support - if (goog.userAgent.IE && !goog.userAgent.isVersion('7')) { - classNames.push.apply(classNames, - this.getAppliedCombinedClassNames_(classNames)); - } - - return classNames; -}; - - -/** - * Returns an array of all the combined class names that should be applied based - * on the given list of classes. Checks the result of - * {@link getIe6ClassCombinations} for any combinations that have all - * members contained in classes. If a combination matches, the members are - * joined with an underscore (in order), and added to the return array. - * - * If opt_includedClass is provided, return only the combined classes that have - * all members contained in classes AND include opt_includedClass as well. - * opt_includedClass is added to classes as well. - * @param {Array.<string>} classes Array of classes to return matching combined - * classes for. - * @param {?string=} opt_includedClass If provided, get only the combined - * classes that include this one. - * @return {Array.<string>} Array of combined class names that should be - * applied. - * @private - */ -goog.ui.ControlRenderer.prototype.getAppliedCombinedClassNames_ = function( - classes, opt_includedClass) { - var toAdd = []; - if (opt_includedClass) { - classes = classes.concat([opt_includedClass]); - } - goog.array.forEach(this.getIe6ClassCombinations(), function(combo) { - if (goog.array.every(combo, goog.partial(goog.array.contains, classes)) && - (!opt_includedClass || goog.array.contains(combo, opt_includedClass))) { - toAdd.push(combo.join('_')); - } - }); - return toAdd; -}; - - -/** - * Takes a bit mask of {@link goog.ui.Component.State}s, and returns an array - * of the appropriate class names representing the given state, suitable to be - * applied to the root element of a component rendered using this renderer, or - * null if no state-specific classes need to be applied. This default - * implementation uses the renderer's {@link getClassForState} method to - * generate each state-specific class. - * @param {number} state Bit mask of component states. - * @return {!Array.<string>} Array of CSS class names representing the given - * state. - * @protected - */ -goog.ui.ControlRenderer.prototype.getClassNamesForState = function(state) { - var classNames = []; - while (state) { - // For each enabled state, push the corresponding CSS class name onto - // the classNames array. - var mask = state & -state; // Least significant bit - classNames.push(this.getClassForState( - /** @type {goog.ui.Component.State} */ (mask))); - state &= ~mask; - } - return classNames; -}; - - -/** - * Takes a single {@link goog.ui.Component.State}, and returns the - * corresponding CSS class name (null if none). - * @param {goog.ui.Component.State} state Component state. - * @return {string|undefined} CSS class representing the given state (undefined - * if none). - * @protected - */ -goog.ui.ControlRenderer.prototype.getClassForState = function(state) { - if (!this.classByState_) { - this.createClassByStateMap_(); - } - return this.classByState_[state]; -}; - - -/** - * Takes a single CSS class name which may represent a component state, and - * returns the corresponding component state (0x00 if none). - * @param {string} className CSS class name, possibly representing a component - * state. - * @return {goog.ui.Component.State} state Component state corresponding - * to the given CSS class (0x00 if none). - * @protected - */ -goog.ui.ControlRenderer.prototype.getStateFromClass = function(className) { - if (!this.stateByClass_) { - this.createStateByClassMap_(); - } - var state = parseInt(this.stateByClass_[className], 10); - return /** @type {goog.ui.Component.State} */ (isNaN(state) ? 0x00 : state); -}; - - -/** - * Creates the lookup table of states to classes, used during state changes. - * @private - */ -goog.ui.ControlRenderer.prototype.createClassByStateMap_ = function() { - var baseClass = this.getStructuralCssClass(); - - /** - * Map of component states to state-specific structural class names, - * used when changing the DOM in response to a state change. Precomputed - * and cached on first use to minimize object allocations and string - * concatenation. - * @type {Object} - * @private - */ - this.classByState_ = goog.object.create( - goog.ui.Component.State.DISABLED, goog.getCssName(baseClass, 'disabled'), - goog.ui.Component.State.HOVER, goog.getCssName(baseClass, 'hover'), - goog.ui.Component.State.ACTIVE, goog.getCssName(baseClass, 'active'), - goog.ui.Component.State.SELECTED, goog.getCssName(baseClass, 'selected'), - goog.ui.Component.State.CHECKED, goog.getCssName(baseClass, 'checked'), - goog.ui.Component.State.FOCUSED, goog.getCssName(baseClass, 'focused'), - goog.ui.Component.State.OPENED, goog.getCssName(baseClass, 'open')); -}; - - -/** - * Creates the lookup table of classes to states, used during decoration. - * @private - */ -goog.ui.ControlRenderer.prototype.createStateByClassMap_ = function() { - // We need the classByState_ map so we can transpose it. - if (!this.classByState_) { - this.createClassByStateMap_(); - } - - /** - * Map of state-specific structural class names to component states, - * used during element decoration. Precomputed and cached on first use - * to minimize object allocations and string concatenation. - * @type {Object} - * @private - */ - this.stateByClass_ = goog.object.transpose(this.classByState_); -}; |