| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2011 The Native Client SDK Authors. |
| 2 // Use of this source code is governed by a BSD-style license that can |
| 3 // be 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 kinds of drag events: |
| 9 * DRAG_START, DRAG and DRAG_END. |
| 10 */ |
| 11 |
| 12 // The uikit namespace. |
| 13 var uikit = uikit || {}; |
| 14 |
| 15 /** |
| 16 * Constructor for the Dragger. Register for mousedown events that happen on |
| 17 * |opt_target|. If |opt_target| is null or undefined, then this object |
| 18 * observes mousedown on the whole document. |
| 19 * @param {?Element} opt_target The event target. Defaults to the whole |
| 20 * document. |
| 21 * @constructor |
| 22 */ |
| 23 uikit.Dragger = function(target) { |
| 24 /** |
| 25 * The event target. |
| 26 * @type {Element} |
| 27 * @private |
| 28 */ |
| 29 this.target_ = target || document; |
| 30 |
| 31 /** |
| 32 * The array of objects that is notified of drag events. Each object in |
| 33 * this array get sent a handleStartDrag(), handleDrag() and handleEndDrag() |
| 34 * message. |
| 35 * @type {Array.<Object>} |
| 36 * @private |
| 37 */ |
| 38 this.listeners_ = []; |
| 39 |
| 40 /** |
| 41 * Flag to indicate whether the object is in a drag sequence or not. |
| 42 * @type {boolean} |
| 43 * @private |
| 44 */ |
| 45 this.isDragging_ = false; |
| 46 |
| 47 /** |
| 48 * The function objects that get attached as event handlers. These are |
| 49 * cached so that they can be removed on mouse up. |
| 50 * @type {function} |
| 51 * @private |
| 52 */ |
| 53 this.boundMouseMove_ = null; |
| 54 this.boundMouseUp_ = null; |
| 55 |
| 56 this.target_.addEventListener('mousedown', |
| 57 this.onMouseDown.bind(this), |
| 58 false); |
| 59 } |
| 60 |
| 61 /** |
| 62 * The ids used for drag event types. |
| 63 * @enum {string} |
| 64 */ |
| 65 uikit.Dragger.DragEvents = { |
| 66 DRAG_START: 'dragstart', // Start a drag sequence |
| 67 DRAG: 'drag', // Mouse moved during a drag sequence. |
| 68 DRAG_END: 'dragend' // End a drag sewquence. |
| 69 }; |
| 70 |
| 71 /** |
| 72 * Add a drag listener. Each listener should respond to three methods: |
| 73 * handleStartDrag(), handleDrag() and handleEndDrag(). This method assumes |
| 74 * that |listener| does not already exist in the array of listeners. |
| 75 * @param {!Object} listener The object that will listen to drag events. |
| 76 */ |
| 77 uikit.Dragger.prototype.addDragListener = function(listener) { |
| 78 this.listeners_.push(listener); |
| 79 } |
| 80 |
| 81 /** |
| 82 * Handle a mousedown event: register for mousemove and mouseup, then tell |
| 83 * the target that is has a DRAG_START event. |
| 84 * @param {Event} event The mousedown event that triggered this method. For |
| 85 * more information on the DOM Event object, see: |
| 86 * http://www.w3.org/TR/DOM-Level-3-Events/#events-mouseevents |
| 87 */ |
| 88 uikit.Dragger.prototype.onMouseDown = function(event) { |
| 89 this.boundMouseMove_ = this.onMouseMove.bind(this); |
| 90 this.boundMouseUp_ = this.onMouseUp.bind(this); |
| 91 this.target_.addEventListener('mousemove', this.boundMouseMove_); |
| 92 this.target_.addEventListener('mouseup', this.boundMouseUp_); |
| 93 this.isDragging_ = true; |
| 94 // Note: the offsetX/Y properties of the event are used because they are |
| 95 // relative to the top-left of the target which gets |event|. The clientX/Y |
| 96 // properties are relative to the window. |
| 97 // TODO(dspringer): offsetX/Y are *not* part of the w3 DOM spec. Need to |
| 98 // figure out how to do this with clientX/Y. |
| 99 var dragStartEvent = { type: uikit.Dragger.DragEvents.DRAG_START, |
| 100 clientX: event.offsetX, |
| 101 clientY: event.offsetY }; |
| 102 var i; |
| 103 for (i = 0; i < this.listeners_.length; ++i) { |
| 104 this.listeners_[i].handleStartDrag(this.target_, dragStartEvent); |
| 105 } |
| 106 } |
| 107 |
| 108 /** |
| 109 * Handle a mousemove event: tell the target that is has a DRAG event. |
| 110 * @param {Event} event The mousemove event that triggered this method. |
| 111 */ |
| 112 uikit.Dragger.prototype.onMouseMove = function(event) { |
| 113 if (!this.isDragging_) |
| 114 return; |
| 115 var dragEvent = { type: uikit.Dragger.DragEvents.DRAG, |
| 116 clientX: event.offsetX, |
| 117 clientY: event.offsetY}; |
| 118 var i; |
| 119 for (i = 0; i < this.listeners_.length; ++i) { |
| 120 this.listeners_[i].handleDrag(this.target_, dragEvent); |
| 121 } |
| 122 } |
| 123 |
| 124 /** |
| 125 * Handle a mouseup event: un-register for mousemove and mouseup, then tell |
| 126 * the target that is has a DRAG_END event. |
| 127 * @param {Event} event The mouseup event that triggered this method. |
| 128 */ |
| 129 uikit.Dragger.prototype.onMouseUp = function(event) { |
| 130 this.target_.removeEventListener('mouseup', this.boundMouseUp_, false); |
| 131 this.target_.removeEventListener('mousemove', this.boundMouseMove_, false); |
| 132 this.boundMouseUp_ = null; |
| 133 this.boundMouseMove_ = null; |
| 134 this.isDragging_ = false; |
| 135 var dragEndEvent = { type: uikit.Dragger.DragEvents.DRAG_END, |
| 136 clientX: event.offsetX, |
| 137 clientY: event.offsetY}; |
| 138 var i; |
| 139 for (i = 0; i < this.listeners_.length; ++i) { |
| 140 this.listeners_[i].handleEndDrag(this.target_, dragEndEvent); |
| 141 } |
| 142 } |
| 143 |
| 144 /** |
| 145 * Bind a scope to a function. Used to bind an object to |this| for event |
| 146 * handlers. |
| 147 * @param {!Object} scope The scope in which the function executes. |scope| |
| 148 * becomes |this| during function execution. |
| 149 * @return {function} the bound version of the original function. |
| 150 */ |
| 151 Function.prototype.bind = function(scope) { |
| 152 var boundContext = this; |
| 153 return function() { |
| 154 return boundContext.apply(scope, arguments); |
| 155 } |
| 156 } |
| OLD | NEW |