1 // Copyright 2014 The ChromeOS IME Authors. All Rights Reserved.
2 // limitations under the License.
3 // See the License for the specific language governing permissions and
4 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5 // distributed under the License is distributed on an "AS-IS" BASIS,
6 // Unless required by applicable law or agreed to in writing, software
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // You may obtain a copy of the License at
11 // you may not use this file except in compliance with the License.
12 // Licensed under the Apache License, Version 2.0 (the "License");
14 goog.provide('i18n.input.chrome.inputview.handler.PointerHandler');
16 goog.require('goog.Timer');
17 goog.require('goog.events.EventHandler');
18 goog.require('goog.events.EventTarget');
19 goog.require('goog.events.EventType');
20 goog.require('i18n.input.chrome.inputview.handler.PointerActionBundle');
21 goog.require('i18n.input.chrome.inputview.handler.Util');
23 goog.scope(function() {
28 * The pointer controller.
30 * @param {!Element=} opt_target .
32 * @extends {goog.events.EventTarget}
34 i18n.input.chrome.inputview.handler.PointerHandler = function(opt_target) {
38 * The pointer handlers.
40 * @type {!Object.<number, !i18n.input.chrome.inputview.handler.PointerActionBundle>}
43 this.pointerActionBundles_ = {};
48 * @type {!goog.events.EventHandler}
51 this.eventHandler_ = new goog.events.EventHandler(this);
53 var target = opt_target || document;
55 listen(target, [goog.events.EventType.MOUSEDOWN,
56 goog.events.EventType.TOUCHSTART], this.onPointerDown_, true).
57 listen(document, goog.events.EventType.TOUCHEND, this.onPointerUp_, true).
58 listen(document, goog.events.EventType.MOUSEUP, this.onPointerUp_, true).
59 listen(target, [goog.events.EventType.TOUCHMOVE,
60 goog.events.EventType.MOUSEMOVE], this.onPointerMove_,
63 goog.inherits(i18n.input.chrome.inputview.handler.PointerHandler,
64 goog.events.EventTarget);
65 var PointerHandler = i18n.input.chrome.inputview.handler.PointerHandler;
66 var PointerActionBundle =
67 i18n.input.chrome.inputview.handler.PointerActionBundle;
68 var Util = i18n.input.chrome.inputview.handler.Util;
72 * The canvas class name.
76 PointerHandler.CANVAS_CLASS_NAME_ = 'ita-hwt-canvas';
80 * Mouse down tick, which is for delayed pointer up for tap action on touchpad.
84 PointerHandler.prototype.mouseDownTick_ = null;
88 * Event handler for previous mousedown or touchstart target.
90 * @private {i18n.input.chrome.inputview.handler.PointerActionBundle}
92 PointerHandler.prototype.previousPointerActionBundle_ = null;
96 * Pointer action bundle for mouse down.
97 * This is used in mouse up handler because mouse up event may have different
98 * target than the mouse down event.
100 * @private {i18n.input.chrome.inputview.handler.PointerActionBundle}
102 PointerHandler.prototype.pointerActionBundleForMouseDown_ = null;
106 * Gets the pointer handler for |view|. If not exists, creates a new one.
108 * @param {!i18n.input.chrome.inputview.elements.Element} view .
109 * @return {!i18n.input.chrome.inputview.handler.PointerActionBundle} .
112 PointerHandler.prototype.getPointerActionBundle_ = function(view) {
113 var uid = goog.getUid(view);
114 if (!this.pointerActionBundles_[uid]) {
115 this.pointerActionBundles_[uid] = new i18n.input.chrome.inputview.handler.
116 PointerActionBundle(view, this);
118 return this.pointerActionBundles_[uid];
123 * Callback for mouse/touch down on the target.
125 * @param {!goog.events.BrowserEvent} e The event.
128 PointerHandler.prototype.onPointerDown_ = function(e) {
129 var view = Util.getView(/** @type {!Node} */ (e.target));
133 var pointerActionBundle = this.getPointerActionBundle_(view);
134 if (this.previousPointerActionBundle_ &&
135 this.previousPointerActionBundle_ != pointerActionBundle) {
136 this.previousPointerActionBundle_.cancelDoubleClick();
138 this.previousPointerActionBundle_ = pointerActionBundle;
139 pointerActionBundle.handlePointerDown(e);
140 if (view.pointerConfig.preventDefault) {
143 if (view.pointerConfig.stopEventPropagation) {
146 if (e.type == goog.events.EventType.MOUSEDOWN) {
147 this.mouseDownTick_ = new Date();
148 this.pointerActionBundleForMouseDown_ = pointerActionBundle;
154 * Callback for pointer out.
156 * @param {!goog.events.BrowserEvent} e The event.
159 PointerHandler.prototype.onPointerUp_ = function(e) {
160 var pointerActionBundle;
161 if (e.type == goog.events.EventType.MOUSEUP) {
162 // If mouseup happens too fast after mousedown, it may be a tap action on
163 // touchpad, so delay the pointer up action so user can see the visual
165 if (this.mouseDownTick_ && new Date() - this.mouseDownTick_ < 10) {
166 goog.Timer.callOnce(this.onPointerUp_.bind(this, e), 50);
169 if (this.pointerActionBundleForMouseDown_) {
170 this.pointerActionBundleForMouseDown_.handlePointerUp(e);
171 pointerActionBundle = this.pointerActionBundleForMouseDown_;
172 this.pointerActionBundleForMouseDown_ = null;
175 var view = Util.getView(/** @type {!Node} */ (e.target));
179 pointerActionBundle = this.pointerActionBundles_[goog.getUid(view)];
180 if (pointerActionBundle) {
181 pointerActionBundle.handlePointerUp(e);
185 if (pointerActionBundle && pointerActionBundle.view &&
186 pointerActionBundle.view.pointerConfig.stopEventPropagation) {
193 * Callback for touchmove or mousemove.
195 * @param {!goog.events.BrowserEvent} e The event.
198 PointerHandler.prototype.onPointerMove_ = function(e) {
199 if (e.type == goog.events.EventType.MOUSEMOVE) {
200 if (this.pointerActionBundleForMouseDown_) {
201 this.pointerActionBundleForMouseDown_.handlePointerMove(
202 /** @type {!Event} */ (e.getBrowserEvent()));
206 var touches = e.getBrowserEvent()['touches'];
207 if (!touches || touches.length == 0) {
210 if (touches.length > 1) {
213 var shouldPreventDefault = false;
214 var shouldStopEventPropagation = false;
215 for (var i = 0; i < touches.length; i++) {
216 var view = Util.getView(/** @type {!Node} */ (touches[i].target));
218 var pointerActionBundle = this.pointerActionBundles_[goog.getUid(view)];
219 if (pointerActionBundle) {
220 pointerActionBundle.handlePointerMove(touches[i]);
222 if (view.pointerConfig.preventDefault) {
223 shouldPreventDefault = true;
225 if (view.pointerConfig.stopEventPropagation) {
226 shouldStopEventPropagation = true;
230 if (shouldPreventDefault) {
233 if (shouldStopEventPropagation) {
240 PointerHandler.prototype.disposeInternal = function() {
241 for (var bundle in this.pointerActionBundles_) {
242 goog.dispose(bundle);
244 goog.dispose(this.eventHandler_);
246 goog.base(this, 'disposeInternal');