blob: b4f59a6a589e0d70b14538382c1f7024090f3cf3 [file] [log] [blame]
// 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 menu item class that supports three state checkbox semantics.
*
* @author eae@google.com (Emil A Eklund)
*/
goog.provide('goog.ui.TriStateMenuItem');
goog.provide('goog.ui.TriStateMenuItem.State');
goog.require('goog.dom.classlist');
goog.require('goog.ui.Component');
goog.require('goog.ui.MenuItem');
goog.require('goog.ui.TriStateMenuItemRenderer');
goog.require('goog.ui.registry');
/**
* Class representing a three state checkbox menu item.
*
* @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 {Object=} 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.
* @param {boolean=} opt_alwaysAllowPartial If true, always allow partial
* state.
* @constructor
* @extends {goog.ui.MenuItem}
* TODO(attila): Figure out how to better integrate this into the
* goog.ui.Control state management framework.
* @final
*/
goog.ui.TriStateMenuItem = function(content, opt_model, opt_domHelper,
opt_renderer, opt_alwaysAllowPartial) {
goog.ui.MenuItem.call(this, content, opt_model, opt_domHelper,
opt_renderer || new goog.ui.TriStateMenuItemRenderer());
this.setCheckable(true);
this.alwaysAllowPartial_ = opt_alwaysAllowPartial || false;
};
goog.inherits(goog.ui.TriStateMenuItem, goog.ui.MenuItem);
/**
* Checked states for component.
* @enum {number}
*/
goog.ui.TriStateMenuItem.State = {
/**
* Component is not checked.
*/
NOT_CHECKED: 0,
/**
* Component is partially checked.
*/
PARTIALLY_CHECKED: 1,
/**
* Component is fully checked.
*/
FULLY_CHECKED: 2
};
/**
* Menu item's checked state.
* @type {goog.ui.TriStateMenuItem.State}
* @private
*/
goog.ui.TriStateMenuItem.prototype.checkState_ =
goog.ui.TriStateMenuItem.State.NOT_CHECKED;
/**
* Whether the partial state can be toggled.
* @type {boolean}
* @private
*/
goog.ui.TriStateMenuItem.prototype.allowPartial_ = false;
/**
* Used to override allowPartial_ to force the third state to always be
* permitted.
* @type {boolean}
* @private
*/
goog.ui.TriStateMenuItem.prototype.alwaysAllowPartial_ = false;
/**
* @return {goog.ui.TriStateMenuItem.State} The menu item's check state.
*/
goog.ui.TriStateMenuItem.prototype.getCheckedState = function() {
return this.checkState_;
};
/**
* Sets the checked state.
* @param {goog.ui.TriStateMenuItem.State} state The checked state.
*/
goog.ui.TriStateMenuItem.prototype.setCheckedState = function(state) {
this.setCheckedState_(state);
this.allowPartial_ =
state == goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED;
};
/**
* Sets the checked state and updates the CSS styling. Dispatches a
* {@code CHECK} or {@code UNCHECK} event prior to changing the component's
* state, which may be caught and canceled to prevent the component from
* changing state.
* @param {goog.ui.TriStateMenuItem.State} state The checked state.
* @private
*/
goog.ui.TriStateMenuItem.prototype.setCheckedState_ = function(state) {
if (this.dispatchEvent(state != goog.ui.TriStateMenuItem.State.NOT_CHECKED ?
goog.ui.Component.EventType.CHECK :
goog.ui.Component.EventType.UNCHECK)) {
this.setState(goog.ui.Component.State.CHECKED,
state != goog.ui.TriStateMenuItem.State.NOT_CHECKED);
this.checkState_ = state;
this.updatedCheckedStateClassNames_();
}
};
/** @override */
goog.ui.TriStateMenuItem.prototype.performActionInternal = function(e) {
switch (this.getCheckedState()) {
case goog.ui.TriStateMenuItem.State.NOT_CHECKED:
this.setCheckedState_(this.alwaysAllowPartial_ || this.allowPartial_ ?
goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED :
goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
break;
case goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED:
this.setCheckedState_(goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
break;
case goog.ui.TriStateMenuItem.State.FULLY_CHECKED:
this.setCheckedState_(goog.ui.TriStateMenuItem.State.NOT_CHECKED);
break;
}
var checkboxClass = goog.getCssName(
this.getRenderer().getCssClass(), 'checkbox');
var clickOnCheckbox = e.target && goog.dom.classlist.contains(
/** @type {!Element} */ (e.target), checkboxClass);
return this.dispatchEvent(clickOnCheckbox || this.allowPartial_ ?
goog.ui.Component.EventType.CHANGE :
goog.ui.Component.EventType.ACTION);
};
/**
* Updates the extra class names applied to the menu item element.
* @private
*/
goog.ui.TriStateMenuItem.prototype.updatedCheckedStateClassNames_ = function() {
var renderer = this.getRenderer();
renderer.enableExtraClassName(
this, goog.getCssName(renderer.getCssClass(), 'partially-checked'),
this.getCheckedState() ==
goog.ui.TriStateMenuItem.State.PARTIALLY_CHECKED);
renderer.enableExtraClassName(
this, goog.getCssName(renderer.getCssClass(), 'fully-checked'),
this.getCheckedState() == goog.ui.TriStateMenuItem.State.FULLY_CHECKED);
};
// Register a decorator factory function for goog.ui.TriStateMenuItemRenderer.
goog.ui.registry.setDecoratorByClassName(
goog.ui.TriStateMenuItemRenderer.CSS_CLASS,
function() {
// TriStateMenuItem defaults to using TriStateMenuItemRenderer.
return new goog.ui.TriStateMenuItem(null);
});