aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/events/actionhandler.js
blob: 764eeb856ed50b89ace675abf8819bf1ed42b39c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// 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 This file contains a class to provide a unified mechanism for
 * CLICK and enter KEYDOWN events. This provides better accessibility by
 * providing the given functionality to a keyboard user which is otherwise
 * would be available only via a mouse click.
 *
 * If there is an existing CLICK listener or planning to be added as below -
 *
 * <code>this.eventHandler_.listen(el, CLICK, this.onClick_);<code>
 *
 * it can be replaced with an ACTION listener as follows:
 *
 * <code>this.eventHandler_.listen(
 *    new goog.events.ActionHandler(el),
 *    ACTION,
 *    this.onAction_);<code>
 *
 */

goog.provide('goog.events.ActionEvent');
goog.provide('goog.events.ActionHandler');
goog.provide('goog.events.ActionHandler.EventType');
goog.provide('goog.events.BeforeActionEvent');

goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');
goog.require('goog.events.KeyCodes');
goog.require('goog.userAgent');



/**
 * A wrapper around an element that you want to listen to ACTION events on.
 * @param {Element|Document} element The element or document to listen on.
 * @constructor
 * @extends {goog.events.EventTarget}
 */
goog.events.ActionHandler = function(element) {
  goog.events.EventTarget.call(this);

  /**
   * This is the element that we will listen to events on.
   * @type {Element|Document}
   * @private
   */
  this.element_ = element;

  goog.events.listen(element, goog.events.ActionHandler.KEY_EVENT_TYPE_,
      this.handleKeyDown_, false, this);
  goog.events.listen(element, goog.events.EventType.CLICK,
      this.handleClick_, false, this);
};
goog.inherits(goog.events.ActionHandler, goog.events.EventTarget);


/**
 * Enum type for the events fired by the action handler
 * @enum {string}
 */
goog.events.ActionHandler.EventType = {
  ACTION: 'action',
  BEFOREACTION: 'beforeaction'
};


/**
 * Key event type to listen for.
 * @type {string}
 * @private
 */
goog.events.ActionHandler.KEY_EVENT_TYPE_ = goog.userAgent.GECKO ?
    goog.events.EventType.KEYPRESS :
    goog.events.EventType.KEYDOWN;


/**
 * Handles key press events.
 * @param {!goog.events.BrowserEvent} e The key press event.
 * @private
 */
goog.events.ActionHandler.prototype.handleKeyDown_ = function(e) {
  if (e.keyCode == goog.events.KeyCodes.ENTER ||
      goog.userAgent.WEBKIT && e.keyCode == goog.events.KeyCodes.MAC_ENTER) {
    this.dispatchEvents_(e);
  }
};


/**
 * Handles mouse events.
 * @param {!goog.events.BrowserEvent} e The click event.
 * @private
 */
goog.events.ActionHandler.prototype.handleClick_ = function(e) {
  this.dispatchEvents_(e);
};


/**
 * Dispatches BeforeAction and Action events to the element
 * @param {!goog.events.BrowserEvent} e The event causing dispatches.
 * @private
 */
goog.events.ActionHandler.prototype.dispatchEvents_ = function(e) {
  var beforeActionEvent = new goog.events.BeforeActionEvent(e);

  // Allow application specific logic here before the ACTION event.
  // For example, Gmail uses this event to restore keyboard focus
  if (!this.dispatchEvent(beforeActionEvent)) {
    // If the listener swallowed the BEFOREACTION event, don't dispatch the
    // ACTION event.
    return;
  }


  // Wrap up original event and send it off
  var actionEvent = new goog.events.ActionEvent(e);
  try {
    this.dispatchEvent(actionEvent);
  } finally {
    // Stop propagating the event
    e.stopPropagation();
  }
};


/** @override */
goog.events.ActionHandler.prototype.disposeInternal = function() {
  goog.events.ActionHandler.superClass_.disposeInternal.call(this);
  goog.events.unlisten(this.element_, goog.events.ActionHandler.KEY_EVENT_TYPE_,
      this.handleKeyDown_, false, this);
  goog.events.unlisten(this.element_, goog.events.EventType.CLICK,
      this.handleClick_, false, this);
  delete this.element_;
};



/**
 * This class is used for the goog.events.ActionHandler.EventType.ACTION event.
 * @param {!goog.events.BrowserEvent} browserEvent Browser event object.
 * @constructor
 * @extends {goog.events.BrowserEvent}
 */
goog.events.ActionEvent = function(browserEvent) {
  goog.events.BrowserEvent.call(this, browserEvent.getBrowserEvent());
  this.type = goog.events.ActionHandler.EventType.ACTION;
};
goog.inherits(goog.events.ActionEvent, goog.events.BrowserEvent);



/**
 * This class is used for the goog.events.ActionHandler.EventType.BEFOREACTION
 * event. BEFOREACTION gives a chance to the application so the keyboard focus
 * can be restored back, if required.
 * @param {!goog.events.BrowserEvent} browserEvent Browser event object.
 * @constructor
 * @extends {goog.events.BrowserEvent}
 */
goog.events.BeforeActionEvent = function(browserEvent) {
  goog.events.BrowserEvent.call(this, browserEvent.getBrowserEvent());
  this.type = goog.events.ActionHandler.EventType.BEFOREACTION;
};
goog.inherits(goog.events.BeforeActionEvent, goog.events.BrowserEvent);