summaryrefslogtreecommitdiff
path: root/chromium/third_party/trace-viewer/src/ui/mouse_tracker.js
blob: 552685fc1bc0deb5689d72128c2f73063f478d20 (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
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

'use strict';

/**
 * @fileoverview A Mouse-event abtraction that waits for
 *   mousedown, then watches for subsequent mousemove events
 *   until the next mouseup event, then waits again.
 *   State changes are signaled with
 *      'mouse-tracker-start' : mousedown and tracking
 *      'mouse-tracker-move' : mouse move
 *      'mouse-tracker-end' : mouseup and not tracking.
 */

base.exportTo('ui', function() {

  /**
   * @constructor
   * @param {HTMLElement} targetElement will recv events 'mouse-tracker-start',
   *     'mouse-tracker-move', 'mouse-tracker-end'.
   */
  function MouseTracker(opt_targetElement) {
    this.onMouseDown_ = this.onMouseDown_.bind(this);
    this.onMouseMove_ = this.onMouseMove_.bind(this);
    this.onMouseUp_ = this.onMouseUp_.bind(this);

    this.targetElement = opt_targetElement;
  }

  MouseTracker.prototype = {

    get targetElement() {
      return this.targetElement_;
    },

    set targetElement(targetElement) {
      if (this.targetElement_)
        this.targetElement_.removeEventListener('mousedown', this.onMouseDown_);
      this.targetElement_ = targetElement;
      if (this.targetElement_)
        this.targetElement_.addEventListener('mousedown', this.onMouseDown_);
    },

    onMouseDown_: function(e) {
      if (e.button !== 0)
        return true;

      e = this.remakeEvent_(e, 'mouse-tracker-start');
      this.targetElement_.dispatchEvent(e);
      document.addEventListener('mousemove', this.onMouseMove_);
      document.addEventListener('mouseup', this.onMouseUp_);
      this.targetElement_.addEventListener('blur', this.onMouseUp_);
      this.savePreviousUserSelect_ = document.body.style['-webkit-user-select'];
      document.body.style['-webkit-user-select'] = 'none';
      e.preventDefault();
      return true;
    },

    onMouseMove_: function(e) {
      e = this.remakeEvent_(e, 'mouse-tracker-move');
      this.targetElement_.dispatchEvent(e);
    },

    onMouseUp_: function(e) {
      document.removeEventListener('mousemove', this.onMouseMove_);
      document.removeEventListener('mouseup', this.onMouseUp_);
      this.targetElement_.removeEventListener('blur', this.onMouseUp_);
      document.body.style['-webkit-user-select'] =
          this.savePreviousUserSelect_;
      e = this.remakeEvent_(e, 'mouse-tracker-end');
      this.targetElement_.dispatchEvent(e);
    },

    remakeEvent_: function(e, newType) {
      var remade = new base.Event(newType, true, true);
      remade.x = e.x;
      remade.y = e.y;
      remade.offsetX = e.offsetX;
      remade.offsetY = e.offsetY;
      remade.clientX = e.clientX;
      remade.clientY = e.clientY;
      return remade;
    }

  };

  function trackMouseMovesUntilMouseUp(mouseMoveHandler, opt_mouseUpHandler) {
    function cleanupAndDispatchToMouseUp(e) {
      document.removeEventListener('mousemove', mouseMoveHandler);
      document.removeEventListener('mouseup', cleanupAndDispatchToMouseUp);
      if (opt_mouseUpHandler)
        opt_mouseUpHandler(e);
    }
    document.addEventListener('mousemove', mouseMoveHandler);
    document.addEventListener('mouseup', cleanupAndDispatchToMouseUp);
  }

  return {
    MouseTracker: MouseTracker,
    trackMouseMovesUntilMouseUp: trackMouseMovesUntilMouseUp
  };
});