Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/fx/dragger.js
2868 views
1
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Drag Utilities.
17
*
18
* Provides extensible functionality for drag & drop behaviour.
19
*
20
* @see ../demos/drag.html
21
* @see ../demos/dragger.html
22
*/
23
24
25
goog.provide('goog.fx.DragEvent');
26
goog.provide('goog.fx.Dragger');
27
goog.provide('goog.fx.Dragger.EventType');
28
29
goog.require('goog.dom');
30
goog.require('goog.dom.TagName');
31
goog.require('goog.events');
32
goog.require('goog.events.Event');
33
goog.require('goog.events.EventHandler');
34
goog.require('goog.events.EventTarget');
35
goog.require('goog.events.EventType');
36
goog.require('goog.math.Coordinate');
37
goog.require('goog.math.Rect');
38
goog.require('goog.style');
39
goog.require('goog.style.bidi');
40
goog.require('goog.userAgent');
41
42
43
44
/**
45
* A class that allows mouse or touch-based dragging (moving) of an element
46
*
47
* @param {Element} target The element that will be dragged.
48
* @param {Element=} opt_handle An optional handle to control the drag, if null
49
* the target is used.
50
* @param {goog.math.Rect=} opt_limits Object containing left, top, width,
51
* and height.
52
*
53
* @extends {goog.events.EventTarget}
54
* @constructor
55
* @struct
56
*/
57
goog.fx.Dragger = function(target, opt_handle, opt_limits) {
58
goog.fx.Dragger.base(this, 'constructor');
59
60
/**
61
* Reference to drag target element.
62
* @type {?Element}
63
*/
64
this.target = target;
65
66
/**
67
* Reference to the handler that initiates the drag.
68
* @type {?Element}
69
*/
70
this.handle = opt_handle || target;
71
72
/**
73
* Object representing the limits of the drag region.
74
* @type {goog.math.Rect}
75
*/
76
this.limits = opt_limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
77
78
/**
79
* Reference to a document object to use for the events.
80
* @private {Document}
81
*/
82
this.document_ = goog.dom.getOwnerDocument(target);
83
84
/** @private {!goog.events.EventHandler} */
85
this.eventHandler_ = new goog.events.EventHandler(this);
86
this.registerDisposable(this.eventHandler_);
87
88
/**
89
* Whether the element is rendered right-to-left. We initialize this lazily.
90
* @private {boolean|undefined}}
91
*/
92
this.rightToLeft_;
93
94
/**
95
* Current x position of mouse or touch relative to viewport.
96
* @type {number}
97
*/
98
this.clientX = 0;
99
100
/**
101
* Current y position of mouse or touch relative to viewport.
102
* @type {number}
103
*/
104
this.clientY = 0;
105
106
/**
107
* Current x position of mouse or touch relative to screen. Deprecated because
108
* it doesn't take into affect zoom level or pixel density.
109
* @type {number}
110
* @deprecated Consider switching to clientX instead.
111
*/
112
this.screenX = 0;
113
114
/**
115
* Current y position of mouse or touch relative to screen. Deprecated because
116
* it doesn't take into affect zoom level or pixel density.
117
* @type {number}
118
* @deprecated Consider switching to clientY instead.
119
*/
120
this.screenY = 0;
121
122
/**
123
* The x position where the first mousedown or touchstart occurred.
124
* @type {number}
125
*/
126
this.startX = 0;
127
128
/**
129
* The y position where the first mousedown or touchstart occurred.
130
* @type {number}
131
*/
132
this.startY = 0;
133
134
/**
135
* Current x position of drag relative to target's parent.
136
* @type {number}
137
*/
138
this.deltaX = 0;
139
140
/**
141
* Current y position of drag relative to target's parent.
142
* @type {number}
143
*/
144
this.deltaY = 0;
145
146
/**
147
* The current page scroll value.
148
* @type {?goog.math.Coordinate}
149
*/
150
this.pageScroll;
151
152
/**
153
* Whether dragging is currently enabled.
154
* @private {boolean}
155
*/
156
this.enabled_ = true;
157
158
/**
159
* Whether object is currently being dragged.
160
* @private {boolean}
161
*/
162
this.dragging_ = false;
163
164
/**
165
* Whether mousedown should be default prevented.
166
* @private {boolean}
167
**/
168
this.preventMouseDown_ = true;
169
170
/**
171
* The amount of distance, in pixels, after which a mousedown or touchstart is
172
* considered a drag.
173
* @private {number}
174
*/
175
this.hysteresisDistanceSquared_ = 0;
176
177
/**
178
* The SCROLL event target used to make drag element follow scrolling.
179
* @private {?EventTarget}
180
*/
181
this.scrollTarget_;
182
183
/**
184
* Whether IE drag events cancelling is on.
185
* @private {boolean}
186
*/
187
this.ieDragStartCancellingOn_ = false;
188
189
/**
190
* Whether the dragger implements the changes described in http://b/6324964,
191
* making it truly RTL. This is a temporary flag to allow clients to
192
* transition to the new behavior at their convenience. At some point it will
193
* be the default.
194
* @private {boolean}
195
*/
196
this.useRightPositioningForRtl_ = false;
197
198
// Add listener. Do not use the event handler here since the event handler is
199
// used for listeners added and removed during the drag operation.
200
goog.events.listen(
201
this.handle,
202
[goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
203
this.startDrag, false, this);
204
};
205
goog.inherits(goog.fx.Dragger, goog.events.EventTarget);
206
// Dragger is meant to be extended, but defines most properties on its
207
// prototype, thus making it unsuitable for sealing.
208
goog.tagUnsealableClass(goog.fx.Dragger);
209
210
211
/**
212
* Whether setCapture is supported by the browser.
213
* IE and Gecko after 1.9.3 have setCapture. MS Edge and WebKit
214
* (https://bugs.webkit.org/show_bug.cgi?id=27330) don't.
215
* @type {boolean}
216
* @private
217
*/
218
goog.fx.Dragger.HAS_SET_CAPTURE_ = goog.global.document &&
219
goog.global.document.documentElement &&
220
!!goog.global.document.documentElement.setCapture &&
221
!!goog.global.document.releaseCapture;
222
223
224
/**
225
* Creates copy of node being dragged. This is a utility function to be used
226
* wherever it is inappropriate for the original source to follow the mouse
227
* cursor itself.
228
*
229
* @param {Element} sourceEl Element to copy.
230
* @return {!Element} The clone of {@code sourceEl}.
231
*/
232
goog.fx.Dragger.cloneNode = function(sourceEl) {
233
var clonedEl = sourceEl.cloneNode(true),
234
origTexts =
235
goog.dom.getElementsByTagName(goog.dom.TagName.TEXTAREA, sourceEl),
236
dragTexts =
237
goog.dom.getElementsByTagName(goog.dom.TagName.TEXTAREA, clonedEl);
238
// Cloning does not copy the current value of textarea elements, so correct
239
// this manually.
240
for (var i = 0; i < origTexts.length; i++) {
241
dragTexts[i].value = origTexts[i].value;
242
}
243
switch (sourceEl.tagName) {
244
case String(goog.dom.TagName.TR):
245
return goog.dom.createDom(
246
goog.dom.TagName.TABLE, null,
247
goog.dom.createDom(goog.dom.TagName.TBODY, null, clonedEl));
248
case String(goog.dom.TagName.TD):
249
case String(goog.dom.TagName.TH):
250
return goog.dom.createDom(
251
goog.dom.TagName.TABLE, null,
252
goog.dom.createDom(
253
goog.dom.TagName.TBODY, null,
254
goog.dom.createDom(goog.dom.TagName.TR, null, clonedEl)));
255
case String(goog.dom.TagName.TEXTAREA):
256
clonedEl.value = sourceEl.value;
257
default:
258
return clonedEl;
259
}
260
};
261
262
263
/**
264
* Constants for event names.
265
* @enum {string}
266
*/
267
goog.fx.Dragger.EventType = {
268
// The drag action was canceled before the START event. Possible reasons:
269
// disabled dragger, dragging with the right mouse button or releasing the
270
// button before reaching the hysteresis distance.
271
EARLY_CANCEL: 'earlycancel',
272
START: 'start',
273
BEFOREDRAG: 'beforedrag',
274
DRAG: 'drag',
275
END: 'end'
276
};
277
278
279
/**
280
* Turns on/off true RTL behavior. This should be called immediately after
281
* construction. This is a temporary flag to allow clients to transition
282
* to the new component at their convenience. At some point true will be the
283
* default.
284
* @param {boolean} useRightPositioningForRtl True if "right" should be used for
285
* positioning, false if "left" should be used for positioning.
286
*/
287
goog.fx.Dragger.prototype.enableRightPositioningForRtl = function(
288
useRightPositioningForRtl) {
289
this.useRightPositioningForRtl_ = useRightPositioningForRtl;
290
};
291
292
293
/**
294
* Returns the event handler, intended for subclass use.
295
* @return {!goog.events.EventHandler<T>} The event handler.
296
* @this {T}
297
* @template T
298
*/
299
goog.fx.Dragger.prototype.getHandler = function() {
300
// TODO(user): templated "this" values currently result in "this" being
301
// "unknown" in the body of the function.
302
var self = /** @type {goog.fx.Dragger} */ (this);
303
return self.eventHandler_;
304
};
305
306
307
/**
308
* Sets (or reset) the Drag limits after a Dragger is created.
309
* @param {goog.math.Rect?} limits Object containing left, top, width,
310
* height for new Dragger limits. If target is right-to-left and
311
* enableRightPositioningForRtl(true) is called, then rect is interpreted as
312
* right, top, width, and height.
313
*/
314
goog.fx.Dragger.prototype.setLimits = function(limits) {
315
this.limits = limits || new goog.math.Rect(NaN, NaN, NaN, NaN);
316
};
317
318
319
/**
320
* Sets the distance the user has to drag the element before a drag operation is
321
* started.
322
* @param {number} distance The number of pixels after which a mousedown and
323
* move is considered a drag.
324
*/
325
goog.fx.Dragger.prototype.setHysteresis = function(distance) {
326
this.hysteresisDistanceSquared_ = Math.pow(distance, 2);
327
};
328
329
330
/**
331
* Gets the distance the user has to drag the element before a drag operation is
332
* started.
333
* @return {number} distance The number of pixels after which a mousedown and
334
* move is considered a drag.
335
*/
336
goog.fx.Dragger.prototype.getHysteresis = function() {
337
return Math.sqrt(this.hysteresisDistanceSquared_);
338
};
339
340
341
/**
342
* Sets the SCROLL event target to make drag element follow scrolling.
343
*
344
* @param {EventTarget} scrollTarget The event target that dispatches SCROLL
345
* events.
346
*/
347
goog.fx.Dragger.prototype.setScrollTarget = function(scrollTarget) {
348
this.scrollTarget_ = scrollTarget;
349
};
350
351
352
/**
353
* Enables cancelling of built-in IE drag events.
354
* @param {boolean} cancelIeDragStart Whether to enable cancelling of IE
355
* dragstart event.
356
*/
357
goog.fx.Dragger.prototype.setCancelIeDragStart = function(cancelIeDragStart) {
358
this.ieDragStartCancellingOn_ = cancelIeDragStart;
359
};
360
361
362
/**
363
* @return {boolean} Whether the dragger is enabled.
364
*/
365
goog.fx.Dragger.prototype.getEnabled = function() {
366
return this.enabled_;
367
};
368
369
370
/**
371
* Set whether dragger is enabled
372
* @param {boolean} enabled Whether dragger is enabled.
373
*/
374
goog.fx.Dragger.prototype.setEnabled = function(enabled) {
375
this.enabled_ = enabled;
376
};
377
378
379
/**
380
* Set whether mousedown should be default prevented.
381
* @param {boolean} preventMouseDown Whether mousedown should be default
382
* prevented.
383
*/
384
goog.fx.Dragger.prototype.setPreventMouseDown = function(preventMouseDown) {
385
this.preventMouseDown_ = preventMouseDown;
386
};
387
388
389
/** @override */
390
goog.fx.Dragger.prototype.disposeInternal = function() {
391
goog.fx.Dragger.superClass_.disposeInternal.call(this);
392
goog.events.unlisten(
393
this.handle,
394
[goog.events.EventType.TOUCHSTART, goog.events.EventType.MOUSEDOWN],
395
this.startDrag, false, this);
396
this.cleanUpAfterDragging_();
397
398
this.target = null;
399
this.handle = null;
400
};
401
402
403
/**
404
* Whether the DOM element being manipulated is rendered right-to-left.
405
* @return {boolean} True if the DOM element is rendered right-to-left, false
406
* otherwise.
407
* @private
408
*/
409
goog.fx.Dragger.prototype.isRightToLeft_ = function() {
410
if (!goog.isDef(this.rightToLeft_)) {
411
this.rightToLeft_ = goog.style.isRightToLeft(this.target);
412
}
413
return this.rightToLeft_;
414
};
415
416
417
/**
418
* Event handler that is used to start the drag
419
* @param {goog.events.BrowserEvent} e Event object.
420
*/
421
goog.fx.Dragger.prototype.startDrag = function(e) {
422
var isMouseDown = e.type == goog.events.EventType.MOUSEDOWN;
423
424
// Dragger.startDrag() can be called by AbstractDragDrop with a mousemove
425
// event and IE does not report pressed mouse buttons on mousemove. Also,
426
// it does not make sense to check for the button if the user is already
427
// dragging.
428
429
if (this.enabled_ && !this.dragging_ &&
430
(!isMouseDown || e.isMouseActionButton())) {
431
if (this.hysteresisDistanceSquared_ == 0) {
432
if (this.fireDragStart_(e)) {
433
this.dragging_ = true;
434
if (this.preventMouseDown_ && isMouseDown) {
435
e.preventDefault();
436
}
437
} else {
438
// If the start drag is cancelled, don't setup for a drag.
439
return;
440
}
441
} else if (this.preventMouseDown_ && isMouseDown) {
442
// Need to preventDefault for hysteresis to prevent page getting selected.
443
e.preventDefault();
444
}
445
this.setupDragHandlers();
446
447
this.clientX = this.startX = e.clientX;
448
this.clientY = this.startY = e.clientY;
449
this.screenX = e.screenX;
450
this.screenY = e.screenY;
451
this.computeInitialPosition();
452
this.pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
453
} else {
454
this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
455
}
456
};
457
458
459
/**
460
* Sets up event handlers when dragging starts.
461
* @protected
462
*/
463
goog.fx.Dragger.prototype.setupDragHandlers = function() {
464
var doc = this.document_;
465
var docEl = doc.documentElement;
466
// Use bubbling when we have setCapture since we got reports that IE has
467
// problems with the capturing events in combination with setCapture.
468
var useCapture = !goog.fx.Dragger.HAS_SET_CAPTURE_;
469
470
this.eventHandler_.listen(
471
doc, [goog.events.EventType.TOUCHMOVE, goog.events.EventType.MOUSEMOVE],
472
this.handleMove_, useCapture);
473
this.eventHandler_.listen(
474
doc, [goog.events.EventType.TOUCHEND, goog.events.EventType.MOUSEUP],
475
this.endDrag, useCapture);
476
477
if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
478
docEl.setCapture(false);
479
this.eventHandler_.listen(
480
docEl, goog.events.EventType.LOSECAPTURE, this.endDrag);
481
} else {
482
// Make sure we stop the dragging if the window loses focus.
483
// Don't use capture in this listener because we only want to end the drag
484
// if the actual window loses focus. Since blur events do not bubble we use
485
// a bubbling listener on the window.
486
this.eventHandler_.listen(
487
goog.dom.getWindow(doc), goog.events.EventType.BLUR, this.endDrag);
488
}
489
490
if (goog.userAgent.IE && this.ieDragStartCancellingOn_) {
491
// Cancel IE's 'ondragstart' event.
492
this.eventHandler_.listen(
493
doc, goog.events.EventType.DRAGSTART, goog.events.Event.preventDefault);
494
}
495
496
if (this.scrollTarget_) {
497
this.eventHandler_.listen(
498
this.scrollTarget_, goog.events.EventType.SCROLL, this.onScroll_,
499
useCapture);
500
}
501
};
502
503
504
/**
505
* Fires a goog.fx.Dragger.EventType.START event.
506
* @param {goog.events.BrowserEvent} e Browser event that triggered the drag.
507
* @return {boolean} False iff preventDefault was called on the DragEvent.
508
* @private
509
*/
510
goog.fx.Dragger.prototype.fireDragStart_ = function(e) {
511
return this.dispatchEvent(
512
new goog.fx.DragEvent(
513
goog.fx.Dragger.EventType.START, this, e.clientX, e.clientY, e));
514
};
515
516
517
/**
518
* Unregisters the event handlers that are only active during dragging, and
519
* releases mouse capture.
520
* @private
521
*/
522
goog.fx.Dragger.prototype.cleanUpAfterDragging_ = function() {
523
this.eventHandler_.removeAll();
524
if (goog.fx.Dragger.HAS_SET_CAPTURE_) {
525
this.document_.releaseCapture();
526
}
527
};
528
529
530
/**
531
* Event handler that is used to end the drag.
532
* @param {goog.events.BrowserEvent} e Event object.
533
* @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
534
*/
535
goog.fx.Dragger.prototype.endDrag = function(e, opt_dragCanceled) {
536
this.cleanUpAfterDragging_();
537
538
if (this.dragging_) {
539
this.dragging_ = false;
540
541
var x = this.limitX(this.deltaX);
542
var y = this.limitY(this.deltaY);
543
var dragCanceled =
544
opt_dragCanceled || e.type == goog.events.EventType.TOUCHCANCEL;
545
this.dispatchEvent(
546
new goog.fx.DragEvent(
547
goog.fx.Dragger.EventType.END, this, e.clientX, e.clientY, e, x, y,
548
dragCanceled));
549
} else {
550
this.dispatchEvent(goog.fx.Dragger.EventType.EARLY_CANCEL);
551
}
552
};
553
554
555
/**
556
* Event handler that is used to end the drag by cancelling it.
557
* @param {goog.events.BrowserEvent} e Event object.
558
*/
559
goog.fx.Dragger.prototype.endDragCancel = function(e) {
560
this.endDrag(e, true);
561
};
562
563
564
/**
565
* Event handler that is used on mouse / touch move to update the drag
566
* @param {goog.events.BrowserEvent} e Event object.
567
* @private
568
*/
569
goog.fx.Dragger.prototype.handleMove_ = function(e) {
570
if (this.enabled_) {
571
// dx in right-to-left cases is relative to the right.
572
var sign =
573
this.useRightPositioningForRtl_ && this.isRightToLeft_() ? -1 : 1;
574
var dx = sign * (e.clientX - this.clientX);
575
var dy = e.clientY - this.clientY;
576
this.clientX = e.clientX;
577
this.clientY = e.clientY;
578
this.screenX = e.screenX;
579
this.screenY = e.screenY;
580
581
if (!this.dragging_) {
582
var diffX = this.startX - this.clientX;
583
var diffY = this.startY - this.clientY;
584
var distance = diffX * diffX + diffY * diffY;
585
if (distance > this.hysteresisDistanceSquared_) {
586
if (this.fireDragStart_(e)) {
587
this.dragging_ = true;
588
} else {
589
// DragListGroup disposes of the dragger if BEFOREDRAGSTART is
590
// canceled.
591
if (!this.isDisposed()) {
592
this.endDrag(e);
593
}
594
return;
595
}
596
}
597
}
598
599
var pos = this.calculatePosition_(dx, dy);
600
var x = pos.x;
601
var y = pos.y;
602
603
if (this.dragging_) {
604
var rv = this.dispatchEvent(
605
new goog.fx.DragEvent(
606
goog.fx.Dragger.EventType.BEFOREDRAG, this, e.clientX, e.clientY,
607
e, x, y));
608
609
// Only do the defaultAction and dispatch drag event if predrag didn't
610
// prevent default
611
if (rv) {
612
this.doDrag(e, x, y, false);
613
e.preventDefault();
614
}
615
}
616
}
617
};
618
619
620
/**
621
* Calculates the drag position.
622
*
623
* @param {number} dx The horizontal movement delta.
624
* @param {number} dy The vertical movement delta.
625
* @return {!goog.math.Coordinate} The newly calculated drag element position.
626
* @private
627
*/
628
goog.fx.Dragger.prototype.calculatePosition_ = function(dx, dy) {
629
// Update the position for any change in body scrolling
630
var pageScroll = goog.dom.getDomHelper(this.document_).getDocumentScroll();
631
dx += pageScroll.x - this.pageScroll.x;
632
dy += pageScroll.y - this.pageScroll.y;
633
this.pageScroll = pageScroll;
634
635
this.deltaX += dx;
636
this.deltaY += dy;
637
638
var x = this.limitX(this.deltaX);
639
var y = this.limitY(this.deltaY);
640
return new goog.math.Coordinate(x, y);
641
};
642
643
644
/**
645
* Event handler for scroll target scrolling.
646
* @param {goog.events.BrowserEvent} e The event.
647
* @private
648
*/
649
goog.fx.Dragger.prototype.onScroll_ = function(e) {
650
var pos = this.calculatePosition_(0, 0);
651
e.clientX = this.clientX;
652
e.clientY = this.clientY;
653
this.doDrag(e, pos.x, pos.y, true);
654
};
655
656
657
/**
658
* @param {goog.events.BrowserEvent} e The closure object
659
* representing the browser event that caused a drag event.
660
* @param {number} x The new horizontal position for the drag element.
661
* @param {number} y The new vertical position for the drag element.
662
* @param {boolean} dragFromScroll Whether dragging was caused by scrolling
663
* the associated scroll target.
664
* @protected
665
*/
666
goog.fx.Dragger.prototype.doDrag = function(e, x, y, dragFromScroll) {
667
this.defaultAction(x, y);
668
this.dispatchEvent(
669
new goog.fx.DragEvent(
670
goog.fx.Dragger.EventType.DRAG, this, e.clientX, e.clientY, e, x, y));
671
};
672
673
674
/**
675
* Returns the 'real' x after limits are applied (allows for some
676
* limits to be undefined).
677
* @param {number} x X-coordinate to limit.
678
* @return {number} The 'real' X-coordinate after limits are applied.
679
*/
680
goog.fx.Dragger.prototype.limitX = function(x) {
681
var rect = this.limits;
682
var left = !isNaN(rect.left) ? rect.left : null;
683
var width = !isNaN(rect.width) ? rect.width : 0;
684
var maxX = left != null ? left + width : Infinity;
685
var minX = left != null ? left : -Infinity;
686
return Math.min(maxX, Math.max(minX, x));
687
};
688
689
690
/**
691
* Returns the 'real' y after limits are applied (allows for some
692
* limits to be undefined).
693
* @param {number} y Y-coordinate to limit.
694
* @return {number} The 'real' Y-coordinate after limits are applied.
695
*/
696
goog.fx.Dragger.prototype.limitY = function(y) {
697
var rect = this.limits;
698
var top = !isNaN(rect.top) ? rect.top : null;
699
var height = !isNaN(rect.height) ? rect.height : 0;
700
var maxY = top != null ? top + height : Infinity;
701
var minY = top != null ? top : -Infinity;
702
return Math.min(maxY, Math.max(minY, y));
703
};
704
705
706
/**
707
* Overridable function for computing the initial position of the target
708
* before dragging begins.
709
* @protected
710
*/
711
goog.fx.Dragger.prototype.computeInitialPosition = function() {
712
this.deltaX = this.useRightPositioningForRtl_ ?
713
goog.style.bidi.getOffsetStart(this.target) :
714
/** @type {!HTMLElement} */ (this.target).offsetLeft;
715
this.deltaY = /** @type {!HTMLElement} */ (this.target).offsetTop;
716
};
717
718
719
/**
720
* Overridable function for handling the default action of the drag behaviour.
721
* Normally this is simply moving the element to x,y though in some cases it
722
* might be used to resize the layer. This is basically a shortcut to
723
* implementing a default ondrag event handler.
724
* @param {number} x X-coordinate for target element. In right-to-left, x this
725
* is the number of pixels the target should be moved to from the right.
726
* @param {number} y Y-coordinate for target element.
727
*/
728
goog.fx.Dragger.prototype.defaultAction = function(x, y) {
729
if (this.useRightPositioningForRtl_ && this.isRightToLeft_()) {
730
this.target.style.right = x + 'px';
731
} else {
732
this.target.style.left = x + 'px';
733
}
734
this.target.style.top = y + 'px';
735
};
736
737
738
/**
739
* @return {boolean} Whether the dragger is currently in the midst of a drag.
740
*/
741
goog.fx.Dragger.prototype.isDragging = function() {
742
return this.dragging_;
743
};
744
745
746
747
/**
748
* Object representing a drag event
749
* @param {string} type Event type.
750
* @param {goog.fx.Dragger} dragobj Drag object initiating event.
751
* @param {number} clientX X-coordinate relative to the viewport.
752
* @param {number} clientY Y-coordinate relative to the viewport.
753
* @param {goog.events.BrowserEvent} browserEvent The closure object
754
* representing the browser event that caused this drag event.
755
* @param {number=} opt_actX Optional actual x for drag if it has been limited.
756
* @param {number=} opt_actY Optional actual y for drag if it has been limited.
757
* @param {boolean=} opt_dragCanceled Whether the drag has been canceled.
758
* @constructor
759
* @struct
760
* @extends {goog.events.Event}
761
*/
762
goog.fx.DragEvent = function(
763
type, dragobj, clientX, clientY, browserEvent, opt_actX, opt_actY,
764
opt_dragCanceled) {
765
goog.events.Event.call(this, type);
766
767
/**
768
* X-coordinate relative to the viewport
769
* @type {number}
770
*/
771
this.clientX = clientX;
772
773
/**
774
* Y-coordinate relative to the viewport
775
* @type {number}
776
*/
777
this.clientY = clientY;
778
779
/**
780
* The closure object representing the browser event that caused this drag
781
* event.
782
* @type {goog.events.BrowserEvent}
783
*/
784
this.browserEvent = browserEvent;
785
786
/**
787
* The real x-position of the drag if it has been limited
788
* @type {number}
789
*/
790
this.left = goog.isDef(opt_actX) ? opt_actX : dragobj.deltaX;
791
792
/**
793
* The real y-position of the drag if it has been limited
794
* @type {number}
795
*/
796
this.top = goog.isDef(opt_actY) ? opt_actY : dragobj.deltaY;
797
798
/**
799
* Reference to the drag object for this event
800
* @type {goog.fx.Dragger}
801
*/
802
this.dragger = dragobj;
803
804
/**
805
* Whether drag was canceled with this event. Used to differentiate between
806
* a legitimate drag END that can result in an action and a drag END which is
807
* a result of a drag cancelation. For now it can happen 1) with drag END
808
* event on FireFox when user drags the mouse out of the window, 2) with
809
* drag END event on IE7 which is generated on MOUSEMOVE event when user
810
* moves the mouse into the document after the mouse button has been
811
* released, 3) when TOUCHCANCEL is raised instead of TOUCHEND (on touch
812
* events).
813
* @type {boolean}
814
*/
815
this.dragCanceled = !!opt_dragCanceled;
816
};
817
goog.inherits(goog.fx.DragEvent, goog.events.Event);
818
819