1<!DOCTYPE html>
2<!--
3Copyright (c) 2014 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7<link rel="import" href="/tracing/base/base.html">
8<script>
9'use strict';
10
11/**
12 * @fileoverview A Mouse-event abtraction that waits for
13 *   mousedown, then watches for subsequent mousemove events
14 *   until the next mouseup event, then waits again.
15 *   State changes are signaled with
16 *      'mouse-tracker-start' : mousedown and tracking
17 *      'mouse-tracker-move' : mouse move
18 *      'mouse-tracker-end' : mouseup and not tracking.
19 */
20
21tr.exportTo('tr.ui.b', function() {
22
23  /**
24   * @constructor
25   * @param {HTMLElement} targetElement will recv events 'mouse-tracker-start',
26   *     'mouse-tracker-move', 'mouse-tracker-end'.
27   */
28  function MouseTracker(opt_targetElement) {
29    this.onMouseDown_ = this.onMouseDown_.bind(this);
30    this.onMouseMove_ = this.onMouseMove_.bind(this);
31    this.onMouseUp_ = this.onMouseUp_.bind(this);
32
33    this.targetElement = opt_targetElement;
34  }
35
36  MouseTracker.prototype = {
37
38    get targetElement() {
39      return this.targetElement_;
40    },
41
42    set targetElement(targetElement) {
43      if (this.targetElement_)
44        this.targetElement_.removeEventListener('mousedown', this.onMouseDown_);
45      this.targetElement_ = targetElement;
46      if (this.targetElement_)
47        this.targetElement_.addEventListener('mousedown', this.onMouseDown_);
48    },
49
50    onMouseDown_: function(e) {
51      if (e.button !== 0)
52        return true;
53
54      e = this.remakeEvent_(e, 'mouse-tracker-start');
55      this.targetElement_.dispatchEvent(e);
56      document.addEventListener('mousemove', this.onMouseMove_);
57      document.addEventListener('mouseup', this.onMouseUp_);
58      this.targetElement_.addEventListener('blur', this.onMouseUp_);
59      this.savePreviousUserSelect_ = document.body.style['-webkit-user-select'];
60      document.body.style['-webkit-user-select'] = 'none';
61      e.preventDefault();
62      return true;
63    },
64
65    onMouseMove_: function(e) {
66      e = this.remakeEvent_(e, 'mouse-tracker-move');
67      this.targetElement_.dispatchEvent(e);
68    },
69
70    onMouseUp_: function(e) {
71      document.removeEventListener('mousemove', this.onMouseMove_);
72      document.removeEventListener('mouseup', this.onMouseUp_);
73      this.targetElement_.removeEventListener('blur', this.onMouseUp_);
74      document.body.style['-webkit-user-select'] =
75          this.savePreviousUserSelect_;
76      e = this.remakeEvent_(e, 'mouse-tracker-end');
77      this.targetElement_.dispatchEvent(e);
78    },
79
80    remakeEvent_: function(e, newType) {
81      var remade = new tr.b.Event(newType, true, true);
82      remade.x = e.x;
83      remade.y = e.y;
84      remade.offsetX = e.offsetX;
85      remade.offsetY = e.offsetY;
86      remade.clientX = e.clientX;
87      remade.clientY = e.clientY;
88      return remade;
89    }
90
91  };
92
93  function trackMouseMovesUntilMouseUp(mouseMoveHandler,
94                                       opt_mouseUpHandler, opt_keyUpHandler) {
95    function cleanupAndDispatchToMouseUp(e) {
96      document.removeEventListener('mousemove', mouseMoveHandler);
97      if (opt_keyUpHandler)
98        document.removeEventListener('keyup', opt_keyUpHandler);
99      document.removeEventListener('mouseup', cleanupAndDispatchToMouseUp);
100      if (opt_mouseUpHandler)
101        opt_mouseUpHandler(e);
102    }
103    document.addEventListener('mousemove', mouseMoveHandler);
104    if (opt_keyUpHandler)
105      document.addEventListener('keyup', opt_keyUpHandler);
106    document.addEventListener('mouseup', cleanupAndDispatchToMouseUp);
107  }
108
109  return {
110    MouseTracker: MouseTracker,
111    trackMouseMovesUntilMouseUp: trackMouseMovesUntilMouseUp
112  };
113});
114</script>
115