Path: blob/trunk/third_party/closure/goog/events/actioneventwrapper.js
2868 views
// Copyright 2009 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Action event wrapper implementation.16* @author [email protected] (Emil A Eklund)17*/1819goog.provide('goog.events.actionEventWrapper');2021goog.require('goog.a11y.aria');22goog.require('goog.a11y.aria.Role');23goog.require('goog.dom');24goog.require('goog.events');25/** @suppress {extraRequire} */26goog.require('goog.events.EventHandler');27goog.require('goog.events.EventType');28goog.require('goog.events.EventWrapper');29goog.require('goog.events.KeyCodes');30goog.require('goog.userAgent');31323334/**35* Event wrapper for action handling. Fires when an element is activated either36* by clicking it or by focusing it and pressing Enter.37*38* @constructor39* @implements {goog.events.EventWrapper}40* @private41*/42goog.events.ActionEventWrapper_ = function() {};4344/**45* @interface46* @private47*/48goog.events.ActionEventWrapper_.FunctionExtension_ = function() {};4950/** @type {!Object|undefined} */51goog.events.ActionEventWrapper_.FunctionExtension_.prototype.scope_;5253/** @type {function(?):?|{handleEvent:function(?):?}|null} */54goog.events.ActionEventWrapper_.FunctionExtension_.prototype.listener_;555657/**58* Singleton instance of ActionEventWrapper_.59* @type {goog.events.ActionEventWrapper_}60*/61goog.events.actionEventWrapper = new goog.events.ActionEventWrapper_();626364/**65* Event types used by the wrapper.66*67* @type {Array<goog.events.EventType>}68* @private69*/70goog.events.ActionEventWrapper_.EVENT_TYPES_ = [71goog.events.EventType.CLICK,72goog.userAgent.GECKO ? goog.events.EventType.KEYPRESS :73goog.events.EventType.KEYDOWN,74goog.events.EventType.KEYUP75];767778/**79* Adds an event listener using the wrapper on a DOM Node or an object that has80* implemented {@link goog.events.EventTarget}. A listener can only be added81* once to an object.82*83* @param {goog.events.ListenableType} target The target to listen to events on.84* @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback85* method, or an object with a handleEvent function.86* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to87* false).88* @param {Object=} opt_scope Element in whose scope to call the listener.89* @param {goog.events.EventHandler=} opt_eventHandler Event handler to add90* listener to.91* @override92*/93goog.events.ActionEventWrapper_.prototype.listen = function(94target, listener, opt_capt, opt_scope, opt_eventHandler) {95var callback = function(e) {96var listenerFn = goog.events.wrapListener(listener);97var role = goog.dom.isElement(e.target) ?98goog.a11y.aria.getRole(/** @type {!Element} */ (e.target)) :99null;100if (e.type == goog.events.EventType.CLICK && e.isMouseActionButton()) {101listenerFn.call(opt_scope, e);102} else if (103(e.keyCode == goog.events.KeyCodes.ENTER ||104e.keyCode == goog.events.KeyCodes.MAC_ENTER) &&105e.type != goog.events.EventType.KEYUP) {106// convert keydown to keypress for backward compatibility.107e.type = goog.events.EventType.KEYPRESS;108listenerFn.call(opt_scope, e);109} else if (110e.keyCode == goog.events.KeyCodes.SPACE &&111e.type == goog.events.EventType.KEYUP &&112(role == goog.a11y.aria.Role.BUTTON ||113role == goog.a11y.aria.Role.TAB)) {114listenerFn.call(opt_scope, e);115e.preventDefault();116}117};118callback.listener_ = listener;119callback.scope_ = opt_scope;120121if (opt_eventHandler) {122opt_eventHandler.listen(123target, goog.events.ActionEventWrapper_.EVENT_TYPES_, callback,124opt_capt);125} else {126goog.events.listen(127target, goog.events.ActionEventWrapper_.EVENT_TYPES_, callback,128opt_capt);129}130};131132133/**134* Removes an event listener added using goog.events.EventWrapper.listen.135*136* @param {goog.events.ListenableType} target The node to remove listener from.137* @param {function(?):?|{handleEvent:function(?):?}|null} listener Callback138* method, or an object with a handleEvent function.139* @param {boolean=} opt_capt Whether to fire in capture phase (defaults to140* false).141* @param {Object=} opt_scope Element in whose scope to call the listener.142* @param {goog.events.EventHandler=} opt_eventHandler Event handler to remove143* listener from.144* @override145*/146goog.events.ActionEventWrapper_.prototype.unlisten = function(147target, listener, opt_capt, opt_scope, opt_eventHandler) {148for (var type, j = 0; type = goog.events.ActionEventWrapper_.EVENT_TYPES_[j];149j++) {150var listeners = goog.events.getListeners(target, type, !!opt_capt);151for (var obj, i = 0; obj = listeners[i]; i++) {152var objListener =153/** @type {!goog.events.ActionEventWrapper_.FunctionExtension_} */ (154obj.listener);155if (objListener.listener_ == listener &&156objListener.scope_ == opt_scope) {157if (opt_eventHandler) {158opt_eventHandler.unlisten(159target, type, obj.listener, opt_capt, opt_scope);160} else {161goog.events.unlisten(target, type, obj.listener, opt_capt, opt_scope);162}163break;164}165}166}167};168169170