Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / NativeClient / bin_html / dragger.js
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6  * @fileoverview  This class implements a mouse-drag event.  It registers for
7  * mousedown events, and when it sees one, starts capturing mousemove events
8  * until it gets a mousup event.  It manufactures three drag events: the
9  * DRAG_START, DRAG and DRAG_END.
10  */
11
12 // Requires bind
13
14 /**
15  * Constructor for the Dragger.  Register for mousedown events that happen on
16  * |opt_target|.  If |opt_target| is null or undefined, then this object
17  * observes mousedown on the whole document.
18  * @param {?Element} opt_target The event target.  Defaults to the whole
19  *     document.
20  * @constructor
21  */
22 tumbler.Dragger = function(opt_target) {
23   /**
24    * The event target.
25    * @type {Element}
26    * @private
27    */
28   this.target_ = opt_target || document;
29
30   /**
31    * The array of objects that get notified of drag events.  Each object in
32    * this array get sent a handleStartDrag(), handleDrag() and handleEndDrag()
33    * message.
34    * @type {Array.<Object>}
35    * @private
36    */
37   this.listeners_ = [];
38
39   /**
40    * Flag to indicate whether the object is in a drag sequence or not.
41    * @type {boolean}
42    * @private
43    */
44   this.isDragging_ = false;
45
46   /**
47    * The function objects that get attached as event handlers.  These are
48    * cached so that they can be removed on mouse up.
49    * @type {function}
50    * @private
51    */
52   this.boundMouseMove_ = null;
53   this.boundMouseUp_ = null;
54
55   this.target_.addEventListener('mousedown',
56                                 this.onMouseDown.bind(this),
57                                 false);
58 }
59
60 /**
61  * The ids used for drag event types.
62  * @enum {string}
63  */
64 tumbler.Dragger.DragEvents = {
65   DRAG_START: 'dragstart',  // Start a drag sequence
66   DRAG: 'drag',  // Mouse moved during a drag sequence.
67   DRAG_END: 'dragend'  // End a drag sewquence.
68 };
69
70 /**
71  * Add a drag listener.  Each listener should respond to thhree methods:
72  * handleStartDrag(), handleDrag() and handleEndDrag().  This method assumes
73  * that |listener| does not already exist in the array of listeners.
74  * @param {!Object} listener The object that will listen to drag events.
75  */
76 tumbler.Dragger.prototype.addDragListener = function(listener) {
77   this.listeners_.push(listener);
78 }
79
80 /**
81  * Handle a mousedown event: register for mousemove and mouseup, then tell
82  * the target that is has a DRAG_START event.
83  * @param {Event} event The mousedown event that triggered this method.
84  */
85 tumbler.Dragger.prototype.onMouseDown = function(event) {
86   this.boundMouseMove_ = this.onMouseMove.bind(this);
87   this.boundMouseUp_ = this.onMouseUp.bind(this);
88   this.target_.addEventListener('mousemove', this.boundMouseMove_);
89   this.target_.addEventListener('mouseup', this.boundMouseUp_);
90   this.isDragging_ = true;
91   var dragStartEvent = { type: tumbler.Dragger.DragEvents.DRAG_START,
92                          clientX: event.offsetX,
93                          clientY: event.offsetY };
94   var i;
95   for (i = 0; i < this.listeners_.length; ++i) {
96     this.listeners_[i].handleStartDrag(this.target_, dragStartEvent);
97   }
98 }
99
100 /**
101  * Handle a mousemove event: tell the target that is has a DRAG event.
102  * @param {Event} event The mousemove event that triggered this method.
103  */
104 tumbler.Dragger.prototype.onMouseMove = function(event) {
105   if (!this.isDragging_)
106     return;
107   var dragEvent = { type: tumbler.Dragger.DragEvents.DRAG,
108                     clientX: event.offsetX,
109                     clientY: event.offsetY};
110   var i;
111   for (i = 0; i < this.listeners_.length; ++i) {
112     this.listeners_[i].handleDrag(this.target_, dragEvent);
113   }
114 }
115
116 /**
117  * Handle a mouseup event: un-register for mousemove and mouseup, then tell
118  * the target that is has a DRAG_END event.
119  * @param {Event} event The mouseup event that triggered this method.
120  */
121 tumbler.Dragger.prototype.onMouseUp = function(event) {
122   this.target_.removeEventListener('mouseup', this.boundMouseUp_, false);
123   this.target_.removeEventListener('mousemove', this.boundMouseMove_, false);
124   this.boundMouseUp_ = null;
125   this.boundMouseMove_ = null;
126   this.isDragging_ = false;
127   var dragEndEvent = { type: tumbler.Dragger.DragEvents.DRAG_END,
128                        clientX: event.offsetX,
129                        clientY: event.offsetY};
130   var i;
131   for (i = 0; i < this.listeners_.length; ++i) {
132     this.listeners_[i].handleEndDrag(this.target_, dragEndEvent);
133   }
134 }