Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / third_party / google_input_tools / src / chrome / os / inputview / handler / pointerhandler.js
blob7ca2cc21ecdaa39f7008afc1d0913c287b4648e9
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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() {
27 /**
28  * The pointer controller.
29  *
30  * @param {!Element=} opt_target .
31  * @constructor
32  * @extends {goog.events.EventTarget}
33  */
34 i18n.input.chrome.inputview.handler.PointerHandler = function(opt_target) {
35   goog.base(this);
37   /**
38    * The pointer handlers.
39    *
40    * @type {!Object.<number, !i18n.input.chrome.inputview.handler.PointerActionBundle>}
41    * @private
42    */
43   this.pointerActionBundles_ = {};
45   /**
46    * The event handler.
47    *
48    * @type {!goog.events.EventHandler}
49    * @private
50    */
51   this.eventHandler_ = new goog.events.EventHandler(this);
53   var target = opt_target || document;
54   this.eventHandler_.
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_,
61           true);
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;
71 /**
72  * The canvas class name.
73  * @const {string}
74  * @private
75  */
76 PointerHandler.CANVAS_CLASS_NAME_ = 'ita-hwt-canvas';
79 /**
80  * Mouse down tick, which is for delayed pointer up for tap action on touchpad.
81  *
82  * @private {Date}
83  */
84 PointerHandler.prototype.mouseDownTick_ = null;
87 /**
88  * Event handler for previous mousedown or touchstart target.
89  *
90  * @private {i18n.input.chrome.inputview.handler.PointerActionBundle}
91  */
92 PointerHandler.prototype.previousPointerActionBundle_ = null;
95 /**
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.
99  *
100  * @private {i18n.input.chrome.inputview.handler.PointerActionBundle}
101  */
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} .
110  * @private
111  */
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);
117   }
118   return this.pointerActionBundles_[uid];
123  * Callback for mouse/touch down on the target.
125  * @param {!goog.events.BrowserEvent} e The event.
126  * @private
127  */
128 PointerHandler.prototype.onPointerDown_ = function(e) {
129   var view = Util.getView(/** @type {!Node} */ (e.target));
130   if (!view) {
131     return;
132   }
133   var pointerActionBundle = this.getPointerActionBundle_(view);
134   if (this.previousPointerActionBundle_ &&
135       this.previousPointerActionBundle_ != pointerActionBundle) {
136     this.previousPointerActionBundle_.cancelDoubleClick();
137   }
138   this.previousPointerActionBundle_ = pointerActionBundle;
139   pointerActionBundle.handlePointerDown(e);
140   if (view.pointerConfig.preventDefault) {
141     e.preventDefault();
142   }
143   if (view.pointerConfig.stopEventPropagation) {
144     e.stopPropagation();
145   }
146   if (e.type == goog.events.EventType.MOUSEDOWN) {
147     this.mouseDownTick_ = new Date();
148     this.pointerActionBundleForMouseDown_ = pointerActionBundle;
149   }
154  * Callback for pointer out.
156  * @param {!goog.events.BrowserEvent} e The event.
157  * @private
158  */
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
164     // flash.
165     if (this.mouseDownTick_ && new Date() - this.mouseDownTick_ < 10) {
166       goog.Timer.callOnce(this.onPointerUp_.bind(this, e), 50);
167       return;
168     }
169     if (this.pointerActionBundleForMouseDown_) {
170       this.pointerActionBundleForMouseDown_.handlePointerUp(e);
171       pointerActionBundle = this.pointerActionBundleForMouseDown_;
172       this.pointerActionBundleForMouseDown_ = null;
173     }
174   } else {
175     var view = Util.getView(/** @type {!Node} */ (e.target));
176     if (!view) {
177       return;
178     }
179     pointerActionBundle = this.pointerActionBundles_[goog.getUid(view)];
180     if (pointerActionBundle) {
181       pointerActionBundle.handlePointerUp(e);
182     }
183     e.preventDefault();
184   }
185   if (pointerActionBundle && pointerActionBundle.view &&
186       pointerActionBundle.view.pointerConfig.stopEventPropagation) {
187     e.stopPropagation();
188   }
193  * Callback for touchmove or mousemove.
195  * @param {!goog.events.BrowserEvent} e The event.
196  * @private
197  */
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()));
203     }
204     return;
205   }
206   var touches = e.getBrowserEvent()['touches'];
207   if (!touches || touches.length == 0) {
208     return;
209   }
210   if (touches.length > 1) {
211     e.preventDefault();
212   }
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));
217     if (view) {
218       var pointerActionBundle = this.pointerActionBundles_[goog.getUid(view)];
219       if (pointerActionBundle) {
220         pointerActionBundle.handlePointerMove(touches[i]);
221       }
222       if (view.pointerConfig.preventDefault) {
223         shouldPreventDefault = true;
224       }
225       if (view.pointerConfig.stopEventPropagation) {
226         shouldStopEventPropagation = true;
227       }
228     }
229   }
230   if (shouldPreventDefault) {
231     e.preventDefault();
232   }
233   if (shouldStopEventPropagation) {
234     e.stopPropagation();
235   }
239 /** @override */
240 PointerHandler.prototype.disposeInternal = function() {
241   for (var bundle in this.pointerActionBundles_) {
242     goog.dispose(bundle);
243   }
244   goog.dispose(this.eventHandler_);
246   goog.base(this, 'disposeInternal');
249 });  // goog.scope