123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- // Copyright 2007 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 A class for representing items in menus.
- * @see goog.ui.Menu
- *
- * @author attila@google.com (Attila Bodis)
- * @see ../demos/menuitem.html
- */
- goog.provide('goog.ui.MenuItem');
- goog.require('goog.a11y.aria.Role');
- goog.require('goog.array');
- goog.require('goog.dom');
- goog.require('goog.dom.classlist');
- goog.require('goog.math.Coordinate');
- goog.require('goog.string');
- goog.require('goog.ui.Component');
- goog.require('goog.ui.Control');
- goog.require('goog.ui.MenuItemRenderer');
- goog.require('goog.ui.registry');
- goog.forwardDeclare('goog.ui.Menu'); // circular
- /**
- * Class representing an item in a menu.
- *
- * @param {goog.ui.ControlContent} content Text caption or DOM structure to
- * display as the content of the item (use to add icons or styling to
- * menus).
- * @param {*=} opt_model Data/model associated with the menu item.
- * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper used for
- * document interactions.
- * @param {goog.ui.MenuItemRenderer=} opt_renderer Optional renderer.
- * @constructor
- * @extends {goog.ui.Control}
- */
- goog.ui.MenuItem = function(content, opt_model, opt_domHelper, opt_renderer) {
- goog.ui.Control.call(
- this, content, opt_renderer || goog.ui.MenuItemRenderer.getInstance(),
- opt_domHelper);
- this.setValue(opt_model);
- };
- goog.inherits(goog.ui.MenuItem, goog.ui.Control);
- goog.tagUnsealableClass(goog.ui.MenuItem);
- /**
- * The access key for this menu item. This key allows the user to quickly
- * trigger this item's action with they keyboard. For example, setting the
- * mnenomic key to 70 (F), when the user opens the menu and hits "F," the
- * menu item is triggered.
- *
- * @type {goog.events.KeyCodes}
- * @private
- */
- goog.ui.MenuItem.prototype.mnemonicKey_;
- /**
- * The class set on an element that contains a parenthetical mnemonic key hint.
- * Parenthetical hints are added to items in which the mnemonic key is not found
- * within the menu item's caption itself. For example, if you have a menu item
- * with the caption "Record," but its mnemonic key is "I", the caption displayed
- * in the menu will appear as "Record (I)".
- *
- * @type {string}
- * @private
- */
- goog.ui.MenuItem.MNEMONIC_WRAPPER_CLASS_ =
- goog.getCssName('goog-menuitem-mnemonic-separator');
- /**
- * The class set on an element that contains a keyboard accelerator hint.
- * @type {string}
- */
- goog.ui.MenuItem.ACCELERATOR_CLASS = goog.getCssName('goog-menuitem-accel');
- // goog.ui.Component and goog.ui.Control implementation.
- /**
- * Returns the value associated with the menu item. The default implementation
- * returns the model object associated with the item (if any), or its caption.
- * @return {*} Value associated with the menu item, if any, or its caption.
- */
- goog.ui.MenuItem.prototype.getValue = function() {
- var model = this.getModel();
- return model != null ? model : this.getCaption();
- };
- /**
- * Sets the value associated with the menu item. The default implementation
- * stores the value as the model of the menu item.
- * @param {*} value Value to be associated with the menu item.
- */
- goog.ui.MenuItem.prototype.setValue = function(value) {
- this.setModel(value);
- };
- /** @override */
- goog.ui.MenuItem.prototype.setSupportedState = function(state, support) {
- goog.ui.MenuItem.base(this, 'setSupportedState', state, support);
- switch (state) {
- case goog.ui.Component.State.SELECTED:
- this.setSelectableInternal_(support);
- break;
- case goog.ui.Component.State.CHECKED:
- this.setCheckableInternal_(support);
- break;
- }
- };
- /**
- * Sets the menu item to be selectable or not. Set to true for menu items
- * that represent selectable options.
- * @param {boolean} selectable Whether the menu item is selectable.
- */
- goog.ui.MenuItem.prototype.setSelectable = function(selectable) {
- this.setSupportedState(goog.ui.Component.State.SELECTED, selectable);
- };
- /**
- * Sets the menu item to be selectable or not.
- * @param {boolean} selectable Whether the menu item is selectable.
- * @private
- */
- goog.ui.MenuItem.prototype.setSelectableInternal_ = function(selectable) {
- if (this.isChecked() && !selectable) {
- this.setChecked(false);
- }
- var element = this.getElement();
- if (element) {
- this.getRenderer().setSelectable(this, element, selectable);
- }
- };
- /**
- * Sets the menu item to be checkable or not. Set to true for menu items
- * that represent checkable options.
- * @param {boolean} checkable Whether the menu item is checkable.
- */
- goog.ui.MenuItem.prototype.setCheckable = function(checkable) {
- this.setSupportedState(goog.ui.Component.State.CHECKED, checkable);
- };
- /**
- * Sets the menu item to be checkable or not.
- * @param {boolean} checkable Whether the menu item is checkable.
- * @private
- */
- goog.ui.MenuItem.prototype.setCheckableInternal_ = function(checkable) {
- var element = this.getElement();
- if (element) {
- this.getRenderer().setCheckable(this, element, checkable);
- }
- };
- /**
- * Returns the text caption of the component while ignoring accelerators.
- * @override
- */
- goog.ui.MenuItem.prototype.getCaption = function() {
- var content = this.getContent();
- if (goog.isArray(content)) {
- var acceleratorClass = goog.ui.MenuItem.ACCELERATOR_CLASS;
- var mnemonicWrapClass = goog.ui.MenuItem.MNEMONIC_WRAPPER_CLASS_;
- var caption =
- goog.array
- .map(
- content,
- function(node) {
- if (goog.dom.isElement(node) &&
- (goog.dom.classlist.contains(
- /** @type {!Element} */ (node), acceleratorClass) ||
- goog.dom.classlist.contains(
- /** @type {!Element} */ (node),
- mnemonicWrapClass))) {
- return '';
- } else {
- return goog.dom.getRawTextContent(node);
- }
- })
- .join('');
- return goog.string.collapseBreakingSpaces(caption);
- }
- return goog.ui.MenuItem.superClass_.getCaption.call(this);
- };
- /**
- * @return {?string} The keyboard accelerator text, or null if the menu item
- * doesn't have one.
- */
- goog.ui.MenuItem.prototype.getAccelerator = function() {
- var dom = this.getDomHelper();
- var content = this.getContent();
- if (goog.isArray(content)) {
- var acceleratorEl = goog.array.find(content, function(e) {
- return goog.dom.classlist.contains(
- /** @type {!Element} */ (e), goog.ui.MenuItem.ACCELERATOR_CLASS);
- });
- if (acceleratorEl) {
- return dom.getTextContent(acceleratorEl);
- }
- }
- return null;
- };
- /** @override */
- goog.ui.MenuItem.prototype.handleMouseUp = function(e) {
- var parentMenu = /** @type {goog.ui.Menu} */ (this.getParent());
- if (parentMenu) {
- var oldCoords = parentMenu.openingCoords;
- // Clear out the saved opening coords immediately so they're not used twice.
- parentMenu.openingCoords = null;
- if (oldCoords && goog.isNumber(e.clientX)) {
- var newCoords = new goog.math.Coordinate(e.clientX, e.clientY);
- if (goog.math.Coordinate.equals(oldCoords, newCoords)) {
- // This menu was opened by a mousedown and we're handling the consequent
- // mouseup. The coords haven't changed, meaning this was a simple click,
- // not a click and drag. Don't do the usual behavior because the menu
- // just popped up under the mouse and the user didn't mean to activate
- // this item.
- return;
- }
- }
- }
- goog.ui.MenuItem.base(this, 'handleMouseUp', e);
- };
- /** @override */
- goog.ui.MenuItem.prototype.handleKeyEventInternal = function(e) {
- if (e.keyCode == this.getMnemonic() && this.performActionInternal(e)) {
- return true;
- } else {
- return goog.ui.MenuItem.base(this, 'handleKeyEventInternal', e);
- }
- };
- /**
- * Sets the mnemonic key code. The mnemonic is the key associated with this
- * action.
- * @param {goog.events.KeyCodes} key The key code.
- */
- goog.ui.MenuItem.prototype.setMnemonic = function(key) {
- this.mnemonicKey_ = key;
- };
- /**
- * Gets the mnemonic key code. The mnemonic is the key associated with this
- * action.
- * @return {goog.events.KeyCodes} The key code of the mnemonic key.
- */
- goog.ui.MenuItem.prototype.getMnemonic = function() {
- return this.mnemonicKey_;
- };
- // Register a decorator factory function for goog.ui.MenuItems.
- goog.ui.registry.setDecoratorByClassName(
- goog.ui.MenuItemRenderer.CSS_CLASS, function() {
- // MenuItem defaults to using MenuItemRenderer.
- return new goog.ui.MenuItem(null);
- });
- /**
- * @override
- */
- goog.ui.MenuItem.prototype.getPreferredAriaRole = function() {
- if (this.isSupportedState(goog.ui.Component.State.CHECKED)) {
- return goog.a11y.aria.Role.MENU_ITEM_CHECKBOX;
- }
- if (this.isSupportedState(goog.ui.Component.State.SELECTED)) {
- return goog.a11y.aria.Role.MENU_ITEM_RADIO;
- }
- return goog.ui.MenuItem.base(this, 'getPreferredAriaRole');
- };
- /**
- * @override
- * @return {goog.ui.Menu}
- */
- goog.ui.MenuItem.prototype.getParent = function() {
- return /** @type {goog.ui.Menu} */ (
- goog.ui.Control.prototype.getParent.call(this));
- };
- /**
- * @override
- * @return {goog.ui.Menu}
- */
- goog.ui.MenuItem.prototype.getParentEventTarget = function() {
- return /** @type {goog.ui.Menu} */ (
- goog.ui.Control.prototype.getParentEventTarget.call(this));
- };
|