OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Touch Handler. Class that handles all touch events and | 6 * @fileoverview Touch Handler. Class that handles all touch events and |
7 * uses them to interpret higher level gestures and behaviors. TouchEvent is a | 7 * uses them to interpret higher level gestures and behaviors. TouchEvent is a |
8 * built in mobile safari type: | 8 * built in mobile safari type: |
9 * http://developer.apple.com/safari/library/documentation/UserExperience/Refere
nce/TouchEventClassReference/TouchEvent/TouchEvent.html. | 9 * http://developer.apple.com/safari/library/documentation/UserExperience/Refere
nce/TouchEventClassReference/TouchEvent/TouchEvent.html. |
10 * This class is intended to work with all webkit browsers, tested on Chrome and | 10 * This class is intended to work with all webkit browsers, tested on Chrome and |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 * The type of event sent by TouchHandler | 131 * The type of event sent by TouchHandler |
132 * @constructor | 132 * @constructor |
133 * @extends {Event} | 133 * @extends {Event} |
134 * @param {string} type The type of event (one of cr.ui.Grabber.EventType). | 134 * @param {string} type The type of event (one of cr.ui.Grabber.EventType). |
135 * @param {boolean} bubbles Whether or not the event should bubble. | 135 * @param {boolean} bubbles Whether or not the event should bubble. |
136 * @param {number} clientX The X location of the touch. | 136 * @param {number} clientX The X location of the touch. |
137 * @param {number} clientY The Y location of the touch. | 137 * @param {number} clientY The Y location of the touch. |
138 * @param {!Element} touchedElement The element at the current location of the | 138 * @param {!Element} touchedElement The element at the current location of the |
139 * touch. | 139 * touch. |
140 */ | 140 */ |
141 TouchHandler.Event = function(type, bubbles, clientX, clientY, | 141 TouchHandler.Event = function( |
142 touchedElement) { | 142 type, bubbles, clientX, clientY, touchedElement) { |
143 var event = document.createEvent('Event'); | 143 var event = document.createEvent('Event'); |
144 event.initEvent(type, bubbles, true); | 144 event.initEvent(type, bubbles, true); |
145 event.__proto__ = TouchHandler.Event.prototype; | 145 event.__proto__ = TouchHandler.Event.prototype; |
146 | 146 |
147 /** | 147 /** |
148 * The X location of the touch affected | 148 * The X location of the touch affected |
149 * @type {number} | 149 * @type {number} |
150 */ | 150 */ |
151 event.clientX = clientX; | 151 event.clientX = clientX; |
152 | 152 |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 * during the capture phase. | 348 * during the capture phase. |
349 * @param {boolean=} opt_mouse True if the TouchHandler should generate | 349 * @param {boolean=} opt_mouse True if the TouchHandler should generate |
350 * events for mouse input (in addition to touch input). | 350 * events for mouse input (in addition to touch input). |
351 */ | 351 */ |
352 enable: function(opt_capture, opt_mouse) { | 352 enable: function(opt_capture, opt_mouse) { |
353 var capture = !!opt_capture; | 353 var capture = !!opt_capture; |
354 | 354 |
355 // Just listen to start events for now. When a touch is occuring we'll | 355 // Just listen to start events for now. When a touch is occuring we'll |
356 // want to be subscribed to move and end events on the document, but we | 356 // want to be subscribed to move and end events on the document, but we |
357 // don't want to incur the cost of lots of no-op handlers on the document. | 357 // don't want to incur the cost of lots of no-op handlers on the document. |
358 this.events_.add(this.element_, 'touchstart', this.onStart_.bind(this), | 358 this.events_.add( |
359 capture); | 359 this.element_, 'touchstart', this.onStart_.bind(this), capture); |
360 if (opt_mouse) { | 360 if (opt_mouse) { |
361 this.events_.add(this.element_, 'mousedown', | 361 this.events_.add( |
362 this.mouseToTouchCallback_(this.onStart_.bind(this)), | 362 this.element_, 'mousedown', |
363 capture); | 363 this.mouseToTouchCallback_(this.onStart_.bind(this)), capture); |
364 } | 364 } |
365 | 365 |
366 // If the element is long-pressed, we may need to swallow a click | 366 // If the element is long-pressed, we may need to swallow a click |
367 this.events_.add(this.element_, 'click', this.onClick_.bind(this), true); | 367 this.events_.add(this.element_, 'click', this.onClick_.bind(this), true); |
368 }, | 368 }, |
369 | 369 |
370 /** | 370 /** |
371 * Stop listening to all events. | 371 * Stop listening to all events. |
372 */ | 372 */ |
373 disable: function() { | 373 disable: function() { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 e.targetTouches[0] = touch; | 407 e.targetTouches[0] = touch; |
408 } | 408 } |
409 callback(e); | 409 callback(e); |
410 }; | 410 }; |
411 }, | 411 }, |
412 | 412 |
413 /** | 413 /** |
414 * Begin tracking the touchable element, it is eligible for dragging. | 414 * Begin tracking the touchable element, it is eligible for dragging. |
415 * @private | 415 * @private |
416 */ | 416 */ |
417 beginTracking_: function() { | 417 beginTracking_: function() { this.tracking_ = true; }, |
418 this.tracking_ = true; | |
419 }, | |
420 | 418 |
421 /** | 419 /** |
422 * Stop tracking the touchable element, it is no longer dragging. | 420 * Stop tracking the touchable element, it is no longer dragging. |
423 * @private | 421 * @private |
424 */ | 422 */ |
425 endTracking_: function() { | 423 endTracking_: function() { |
426 this.tracking_ = false; | 424 this.tracking_ = false; |
427 this.dragging_ = false; | 425 this.dragging_ = false; |
428 this.totalMoveY_ = 0; | 426 this.totalMoveY_ = 0; |
429 this.totalMoveX_ = 0; | 427 this.totalMoveX_ = 0; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 // We've just started touching so shouldn't swallow any upcoming click | 487 // We've just started touching so shouldn't swallow any upcoming click |
490 if (this.swallowNextClick_) | 488 if (this.swallowNextClick_) |
491 this.swallowNextClick_ = false; | 489 this.swallowNextClick_ = false; |
492 | 490 |
493 this.disableTap_ = false; | 491 this.disableTap_ = false; |
494 | 492 |
495 // Sign up for end/cancel notifications for this touch. | 493 // Sign up for end/cancel notifications for this touch. |
496 // Note that we do this on the document so that even if the user drags | 494 // Note that we do this on the document so that even if the user drags |
497 // their finger off the element, we'll still know what they're doing. | 495 // their finger off the element, we'll still know what they're doing. |
498 if (e.type == 'mousedown') { | 496 if (e.type == 'mousedown') { |
499 this.events_.add(document, 'mouseup', | 497 this.events_.add( |
| 498 document, 'mouseup', |
500 this.mouseToTouchCallback_(this.onEnd_.bind(this)), false); | 499 this.mouseToTouchCallback_(this.onEnd_.bind(this)), false); |
501 } else { | 500 } else { |
502 this.events_.add(document, 'touchend', this.onEnd_.bind(this), false); | 501 this.events_.add(document, 'touchend', this.onEnd_.bind(this), false); |
503 this.events_.add(document, 'touchcancel', this.onEnd_.bind(this), | 502 this.events_.add( |
504 false); | 503 document, 'touchcancel', this.onEnd_.bind(this), false); |
505 } | 504 } |
506 | 505 |
507 // This timeout is cleared on touchEnd and onDrag | 506 // This timeout is cleared on touchEnd and onDrag |
508 // If we invoke the function then we have a real long press | 507 // If we invoke the function then we have a real long press |
509 window.clearTimeout(this.longPressTimeout_); | 508 window.clearTimeout(this.longPressTimeout_); |
510 this.longPressTimeout_ = window.setTimeout( | 509 this.longPressTimeout_ = window.setTimeout( |
511 this.onLongPress_.bind(this), | 510 this.onLongPress_.bind(this), TouchHandler.TIME_FOR_LONG_PRESS_); |
512 TouchHandler.TIME_FOR_LONG_PRESS_); | |
513 | 511 |
514 // Dispatch the TOUCH_START event | 512 // Dispatch the TOUCH_START event |
515 this.draggingEnabled_ = | 513 this.draggingEnabled_ = |
516 !!this.dispatchEvent_(TouchHandler.EventType.TOUCH_START, touch); | 514 !!this.dispatchEvent_(TouchHandler.EventType.TOUCH_START, touch); |
517 | 515 |
518 // We want dragging notifications | 516 // We want dragging notifications |
519 if (e.type == 'mousedown') { | 517 if (e.type == 'mousedown') { |
520 this.events_.add(document, 'mousemove', | 518 this.events_.add( |
| 519 document, 'mousemove', |
521 this.mouseToTouchCallback_(this.onMove_.bind(this)), false); | 520 this.mouseToTouchCallback_(this.onMove_.bind(this)), false); |
522 } else { | 521 } else { |
523 this.events_.add(document, 'touchmove', this.onMove_.bind(this), false); | 522 this.events_.add(document, 'touchmove', this.onMove_.bind(this), false); |
524 } | 523 } |
525 | 524 |
526 this.startTouchX_ = this.lastTouchX_ = touch.clientX; | 525 this.startTouchX_ = this.lastTouchX_ = touch.clientX; |
527 this.startTouchY_ = this.lastTouchY_ = touch.clientY; | 526 this.startTouchY_ = this.lastTouchY_ = touch.clientY; |
528 this.startTime_ = e.timeStamp; | 527 this.startTime_ = e.timeStamp; |
529 | 528 |
530 this.recentTouchesX_ = []; | 529 this.recentTouchesX_ = []; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 var clientX = touch.clientX; | 573 var clientX = touch.clientX; |
575 var clientY = touch.clientY; | 574 var clientY = touch.clientY; |
576 | 575 |
577 var moveX = this.lastTouchX_ - clientX; | 576 var moveX = this.lastTouchX_ - clientX; |
578 var moveY = this.lastTouchY_ - clientY; | 577 var moveY = this.lastTouchY_ - clientY; |
579 this.totalMoveX_ += Math.abs(moveX); | 578 this.totalMoveX_ += Math.abs(moveX); |
580 this.totalMoveY_ += Math.abs(moveY); | 579 this.totalMoveY_ += Math.abs(moveY); |
581 this.lastTouchX_ = clientX; | 580 this.lastTouchX_ = clientX; |
582 this.lastTouchY_ = clientY; | 581 this.lastTouchY_ = clientY; |
583 | 582 |
584 var couldBeTap = | 583 var couldBeTap = this.totalMoveY_ <= TouchHandler.MAX_TRACKING_FOR_TAP_ || |
585 this.totalMoveY_ <= TouchHandler.MAX_TRACKING_FOR_TAP_ || | |
586 this.totalMoveX_ <= TouchHandler.MAX_TRACKING_FOR_TAP_; | 584 this.totalMoveX_ <= TouchHandler.MAX_TRACKING_FOR_TAP_; |
587 | 585 |
588 if (!couldBeTap) | 586 if (!couldBeTap) |
589 this.disableTap_ = true; | 587 this.disableTap_ = true; |
590 | 588 |
591 if (this.draggingEnabled_ && !this.dragging_ && !couldBeTap) { | 589 if (this.draggingEnabled_ && !this.dragging_ && !couldBeTap) { |
592 // If we're waiting for a long press, stop | 590 // If we're waiting for a long press, stop |
593 window.clearTimeout(this.longPressTimeout_); | 591 window.clearTimeout(this.longPressTimeout_); |
594 | 592 |
595 // Dispatch the DRAG_START event and record whether dragging should be | 593 // Dispatch the DRAG_START event and record whether dragging should be |
596 // allowed or not. Note that this relies on the current value of | 594 // allowed or not. Note that this relies on the current value of |
597 // startTouchX/Y - handlers may use the initial drag delta to determine | 595 // startTouchX/Y - handlers may use the initial drag delta to determine |
598 // if dragging should be permitted. | 596 // if dragging should be permitted. |
599 this.dragging_ = this.dispatchEvent_( | 597 this.dragging_ = |
600 TouchHandler.EventType.DRAG_START, touch); | 598 this.dispatchEvent_(TouchHandler.EventType.DRAG_START, touch); |
601 | 599 |
602 if (this.dragging_) { | 600 if (this.dragging_) { |
603 // Update the start position here so that drag deltas have better | 601 // Update the start position here so that drag deltas have better |
604 // values but don't touch the recent positions so that velocity | 602 // values but don't touch the recent positions so that velocity |
605 // calculations can still use touchstart position in the time and | 603 // calculations can still use touchstart position in the time and |
606 // distance delta. | 604 // distance delta. |
607 this.startTouchX_ = clientX; | 605 this.startTouchX_ = clientX; |
608 this.startTouchY_ = clientY; | 606 this.startTouchY_ = clientY; |
609 this.startTime_ = e.timeStamp; | 607 this.startTime_ = e.timeStamp; |
610 } else { | 608 } else { |
611 this.endTracking_(); | 609 this.endTracking_(); |
612 } | 610 } |
613 } | 611 } |
614 | 612 |
615 if (this.dragging_) { | 613 if (this.dragging_) { |
616 this.dispatchEvent_(TouchHandler.EventType.DRAG_MOVE, touch); | 614 this.dispatchEvent_(TouchHandler.EventType.DRAG_MOVE, touch); |
617 | 615 |
618 this.removeTouchesInWrongDirection_(this.recentTouchesX_, | 616 this.removeTouchesInWrongDirection_( |
619 this.lastMoveX_, moveX); | 617 this.recentTouchesX_, this.lastMoveX_, moveX); |
620 this.removeTouchesInWrongDirection_(this.recentTouchesY_, | 618 this.removeTouchesInWrongDirection_( |
621 this.lastMoveY_, moveY); | 619 this.recentTouchesY_, this.lastMoveY_, moveY); |
622 this.removeOldTouches_(this.recentTouchesX_, e.timeStamp); | 620 this.removeOldTouches_(this.recentTouchesX_, e.timeStamp); |
623 this.removeOldTouches_(this.recentTouchesY_, e.timeStamp); | 621 this.removeOldTouches_(this.recentTouchesY_, e.timeStamp); |
624 this.recentTouchesX_.push(clientX, e.timeStamp); | 622 this.recentTouchesX_.push(clientX, e.timeStamp); |
625 this.recentTouchesY_.push(clientY, e.timeStamp); | 623 this.recentTouchesY_.push(clientY, e.timeStamp); |
626 } | 624 } |
627 | 625 |
628 this.lastMoveX_ = moveX; | 626 this.lastMoveX_ = moveX; |
629 this.lastMoveY_ = moveY; | 627 this.lastMoveY_ = moveY; |
630 }, | 628 }, |
631 | 629 |
632 /** | 630 /** |
633 * Filters the provided recent touches array to remove all touches except | 631 * Filters the provided recent touches array to remove all touches except |
634 * the last if the move direction has changed. | 632 * the last if the move direction has changed. |
635 * @param {!Array<number>} recentTouches An array of tuples where the first | 633 * @param {!Array<number>} recentTouches An array of tuples where the first |
636 * item is the x or y component of the recent touch and the second item | 634 * item is the x or y component of the recent touch and the second item |
637 * is the touch time stamp. | 635 * is the touch time stamp. |
638 * @param {number|undefined} lastMove The x or y component of the previous | 636 * @param {number|undefined} lastMove The x or y component of the previous |
639 * move. | 637 * move. |
640 * @param {number} recentMove The x or y component of the most recent move. | 638 * @param {number} recentMove The x or y component of the most recent move. |
641 * @private | 639 * @private |
642 */ | 640 */ |
643 removeTouchesInWrongDirection_: function(recentTouches, lastMove, | 641 removeTouchesInWrongDirection_: function( |
644 recentMove) { | 642 recentTouches, lastMove, recentMove) { |
645 if (lastMove && recentMove && recentTouches.length > 2 && | 643 if (lastMove && recentMove && recentTouches.length > 2 && |
646 (lastMove > 0 ^ recentMove > 0)) { | 644 (lastMove > 0 ^ recentMove > 0)) { |
647 recentTouches.splice(0, recentTouches.length - 2); | 645 recentTouches.splice(0, recentTouches.length - 2); |
648 } | 646 } |
649 }, | 647 }, |
650 | 648 |
651 /** | 649 /** |
652 * Filters the provided recent touches array to remove all touches older | 650 * Filters the provided recent touches array to remove all touches older |
653 * than the max tracking time or the 5th most recent touch. | 651 * than the max tracking time or the 5th most recent touch. |
654 * @param {!Array<number>} recentTouches An array of tuples where the first | 652 * @param {!Array<number>} recentTouches An array of tuples where the first |
655 * item is the x or y component of the recent touch and the second item | 653 * item is the x or y component of the recent touch and the second item |
656 * is the touch time stamp. | 654 * is the touch time stamp. |
657 * @param {number} recentTime The time of the most recent event. | 655 * @param {number} recentTime The time of the most recent event. |
658 * @private | 656 * @private |
659 */ | 657 */ |
660 removeOldTouches_: function(recentTouches, recentTime) { | 658 removeOldTouches_: function(recentTouches, recentTime) { |
661 while (recentTouches.length && recentTime - recentTouches[1] > | 659 while (recentTouches.length && |
662 TouchHandler.MAX_TRACKING_TIME_ || | 660 recentTime - recentTouches[1] > |
663 recentTouches.length > | 661 TouchHandler.MAX_TRACKING_TIME_ || |
664 TouchHandler.MAX_TRACKING_TOUCHES_ * 2) { | 662 recentTouches.length > TouchHandler.MAX_TRACKING_TOUCHES_ * 2) { |
665 recentTouches.splice(0, 2); | 663 recentTouches.splice(0, 2); |
666 } | 664 } |
667 }, | 665 }, |
668 | 666 |
669 /** | 667 /** |
670 * Touch end handler. | 668 * Touch end handler. |
671 * @param {!TouchEvent} e The touchend event. | 669 * @param {!TouchEvent} e The touchend event. |
672 * @private | 670 * @private |
673 */ | 671 */ |
674 onEnd_: function(e) { | 672 onEnd_: function(e) { |
675 var that = this; | 673 var that = this; |
676 assert(this.activeTouch_ !== undefined, 'Expect to already be touching'); | 674 assert(this.activeTouch_ !== undefined, 'Expect to already be touching'); |
677 | 675 |
678 // If the touch we're tracking isn't changing here, ignore this touch end. | 676 // If the touch we're tracking isn't changing here, ignore this touch end. |
679 var touch = this.findActiveTouch_(e.changedTouches); | 677 var touch = this.findActiveTouch_(e.changedTouches); |
680 if (!touch) { | 678 if (!touch) { |
681 // In most cases, our active touch will be in the 'touches' collection, | 679 // In most cases, our active touch will be in the 'touches' collection, |
682 // but we can't assert that because occasionally two touchend events can | 680 // but we can't assert that because occasionally two touchend events can |
683 // occur at almost the same time with both having empty 'touches' lists. | 681 // occur at almost the same time with both having empty 'touches' lists. |
684 // I.e., 'touches' seems like it can be a bit more up to date than the | 682 // I.e., 'touches' seems like it can be a bit more up to date than the |
685 // current event. | 683 // current event. |
686 return; | 684 return; |
687 } | 685 } |
688 | 686 |
689 // This is touchEnd for the touch we're monitoring | 687 // This is touchEnd for the touch we're monitoring |
690 assert(!this.findActiveTouch_(e.touches), | 688 assert( |
691 'Touch ended also still active'); | 689 !this.findActiveTouch_(e.touches), 'Touch ended also still active'); |
692 | 690 |
693 // Indicate that touching has finished | 691 // Indicate that touching has finished |
694 this.stopTouching_(); | 692 this.stopTouching_(); |
695 | 693 |
696 if (this.tracking_) { | 694 if (this.tracking_) { |
697 var clientX = touch.clientX; | 695 var clientX = touch.clientX; |
698 var clientY = touch.clientY; | 696 var clientY = touch.clientY; |
699 | 697 |
700 if (this.dragging_) { | 698 if (this.dragging_) { |
701 this.endTime_ = e.timeStamp; | 699 this.endTime_ = e.timeStamp; |
(...skipping 30 matching lines...) Expand all Loading... |
732 * drag behavior. End velocity is defined as deltaXY / deltaTime where | 730 * drag behavior. End velocity is defined as deltaXY / deltaTime where |
733 * deltaXY is the difference between endPosition and the oldest recent | 731 * deltaXY is the difference between endPosition and the oldest recent |
734 * position, and deltaTime is the difference between endTime and the oldest | 732 * position, and deltaTime is the difference between endTime and the oldest |
735 * recent time stamp. | 733 * recent time stamp. |
736 * @return {Object} The x and y velocity. | 734 * @return {Object} The x and y velocity. |
737 */ | 735 */ |
738 getEndVelocity: function() { | 736 getEndVelocity: function() { |
739 // Note that we could move velocity to just be an end-event parameter. | 737 // Note that we could move velocity to just be an end-event parameter. |
740 var velocityX = this.recentTouchesX_.length ? | 738 var velocityX = this.recentTouchesX_.length ? |
741 (this.endTouchX_ - this.recentTouchesX_[0]) / | 739 (this.endTouchX_ - this.recentTouchesX_[0]) / |
742 (this.endTime_ - this.recentTouchesX_[1]) : 0; | 740 (this.endTime_ - this.recentTouchesX_[1]) : |
| 741 0; |
743 var velocityY = this.recentTouchesY_.length ? | 742 var velocityY = this.recentTouchesY_.length ? |
744 (this.endTouchY_ - this.recentTouchesY_[0]) / | 743 (this.endTouchY_ - this.recentTouchesY_[0]) / |
745 (this.endTime_ - this.recentTouchesY_[1]) : 0; | 744 (this.endTime_ - this.recentTouchesY_[1]) : |
| 745 0; |
746 | 746 |
747 velocityX = this.correctVelocity_(velocityX); | 747 velocityX = this.correctVelocity_(velocityX); |
748 velocityY = this.correctVelocity_(velocityY); | 748 velocityY = this.correctVelocity_(velocityY); |
749 | 749 |
750 return { | 750 return {x: velocityX, y: velocityY}; |
751 x: velocityX, | |
752 y: velocityY | |
753 }; | |
754 }, | 751 }, |
755 | 752 |
756 /** | 753 /** |
757 * Correct erroneous velocities by capping the velocity if we think it's too | 754 * Correct erroneous velocities by capping the velocity if we think it's too |
758 * high, or setting it to a default velocity if know that the event data is | 755 * high, or setting it to a default velocity if know that the event data is |
759 * bad. | 756 * bad. |
760 * @param {number} velocity The x or y velocity component. | 757 * @param {number} velocity The x or y velocity component. |
761 * @return {number} The corrected velocity. | 758 * @return {number} The corrected velocity. |
762 * @private | 759 * @private |
763 */ | 760 */ |
764 correctVelocity_: function(velocity) { | 761 correctVelocity_: function(velocity) { |
765 var absVelocity = Math.abs(velocity); | 762 var absVelocity = Math.abs(velocity); |
766 | 763 |
767 // We add to recent touches for each touchstart and touchmove. If we have | 764 // We add to recent touches for each touchstart and touchmove. If we have |
768 // fewer than 3 touches (6 entries), we assume that the thread was blocked | 765 // fewer than 3 touches (6 entries), we assume that the thread was blocked |
769 // for the duration of the drag and we received events in quick succession | 766 // for the duration of the drag and we received events in quick succession |
770 // with the wrong time stamps. | 767 // with the wrong time stamps. |
771 if (absVelocity > TouchHandler.MAXIMUM_VELOCITY_) { | 768 if (absVelocity > TouchHandler.MAXIMUM_VELOCITY_) { |
772 absVelocity = this.recentTouchesY_.length < 3 ? | 769 absVelocity = this.recentTouchesY_.length < 3 ? |
773 TouchHandler.VELOCITY_FOR_INCORRECT_EVENTS_ : | 770 TouchHandler.VELOCITY_FOR_INCORRECT_EVENTS_ : |
774 TouchHandler.MAXIMUM_VELOCITY_; | 771 TouchHandler.MAXIMUM_VELOCITY_; |
775 } | 772 } |
776 return absVelocity * (velocity < 0 ? -1 : 1); | 773 return absVelocity * (velocity < 0 ? -1 : 1); |
777 }, | 774 }, |
778 | 775 |
779 /** | 776 /** |
780 * Handler when an element has been pressed for a long time | 777 * Handler when an element has been pressed for a long time |
781 * @private | 778 * @private |
782 */ | 779 */ |
783 onLongPress_: function() { | 780 onLongPress_: function() { |
784 // Swallow any click that occurs on this element without an intervening | 781 // Swallow any click that occurs on this element without an intervening |
785 // touch start event. This simple click-busting technique should be | 782 // touch start event. This simple click-busting technique should be |
786 // sufficient here since a real click should have a touchstart first. | 783 // sufficient here since a real click should have a touchstart first. |
787 this.swallowNextClick_ = true; | 784 this.swallowNextClick_ = true; |
788 this.disableTap_ = true; | 785 this.disableTap_ = true; |
789 | 786 |
790 // Dispatch to the LONG_PRESS | 787 // Dispatch to the LONG_PRESS |
791 assert(typeof this.startTouchX_ == 'number'); | 788 assert(typeof this.startTouchX_ == 'number'); |
792 assert(typeof this.startTouchY_ == 'number'); | 789 assert(typeof this.startTouchY_ == 'number'); |
793 this.dispatchEventXY_(TouchHandler.EventType.LONG_PRESS, this.element_, | 790 this.dispatchEventXY_( |
794 /** @type {number} */(this.startTouchX_), | 791 TouchHandler.EventType.LONG_PRESS, this.element_, |
795 /** @type {number} */(this.startTouchY_)); | 792 /** @type {number} */ (this.startTouchX_), |
| 793 /** @type {number} */ (this.startTouchY_)); |
796 }, | 794 }, |
797 | 795 |
798 /** | 796 /** |
799 * Click handler - used to swallow clicks after a long-press | 797 * Click handler - used to swallow clicks after a long-press |
800 * @param {!Event} e The click event. | 798 * @param {!Event} e The click event. |
801 * @private | 799 * @private |
802 */ | 800 */ |
803 onClick_: function(e) { | 801 onClick_: function(e) { |
804 if (this.swallowNextClick_) { | 802 if (this.swallowNextClick_) { |
805 e.preventDefault(); | 803 e.preventDefault(); |
(...skipping 16 matching lines...) Expand all Loading... |
822 // the event/touch target. But for touch events, the target is always the | 820 // the event/touch target. But for touch events, the target is always the |
823 // target of the touchstart (and it's unlikely we can change this | 821 // target of the touchstart (and it's unlikely we can change this |
824 // since the common implementation of touch dragging relies on it). Since | 822 // since the common implementation of touch dragging relies on it). Since |
825 // touch is our primary scenario (which we want to emulate with mouse), | 823 // touch is our primary scenario (which we want to emulate with mouse), |
826 // we'll treat both cases the same and not depend on the target. | 824 // we'll treat both cases the same and not depend on the target. |
827 /** @type {Element} */ | 825 /** @type {Element} */ |
828 var touchedElement; | 826 var touchedElement; |
829 if (eventType == TouchHandler.EventType.TOUCH_START) { | 827 if (eventType == TouchHandler.EventType.TOUCH_START) { |
830 touchedElement = assertInstanceof(touch.target, Element); | 828 touchedElement = assertInstanceof(touch.target, Element); |
831 } else { | 829 } else { |
832 touchedElement = assert(this.element_.ownerDocument. | 830 touchedElement = assert(this.element_.ownerDocument.elementFromPoint( |
833 elementFromPoint(touch.clientX, touch.clientY)); | 831 touch.clientX, touch.clientY)); |
834 } | 832 } |
835 | 833 |
836 return this.dispatchEventXY_(eventType, touchedElement, touch.clientX, | 834 return this.dispatchEventXY_( |
837 touch.clientY); | 835 eventType, touchedElement, touch.clientX, touch.clientY); |
838 }, | 836 }, |
839 | 837 |
840 /** | 838 /** |
841 * Dispatch a TouchHandler event to the element | 839 * Dispatch a TouchHandler event to the element |
842 * @param {string} eventType The event to dispatch. | 840 * @param {string} eventType The event to dispatch. |
843 * @param {!Element} touchedElement | 841 * @param {!Element} touchedElement |
844 * @param {number} clientX The X location for the event. | 842 * @param {number} clientX The X location for the event. |
845 * @param {number} clientY The Y location for the event. | 843 * @param {number} clientY The Y location for the event. |
846 * @return {boolean|undefined} The value of enableDrag after dispatching | 844 * @return {boolean|undefined} The value of enableDrag after dispatching |
847 * the event. | 845 * the event. |
848 * @private | 846 * @private |
849 */ | 847 */ |
850 dispatchEventXY_: function(eventType, touchedElement, clientX, clientY) { | 848 dispatchEventXY_: function(eventType, touchedElement, clientX, clientY) { |
851 var isDrag = (eventType == TouchHandler.EventType.DRAG_START || | 849 var isDrag = |
852 eventType == TouchHandler.EventType.DRAG_MOVE || | 850 (eventType == TouchHandler.EventType.DRAG_START || |
853 eventType == TouchHandler.EventType.DRAG_END); | 851 eventType == TouchHandler.EventType.DRAG_MOVE || |
| 852 eventType == TouchHandler.EventType.DRAG_END); |
854 | 853 |
855 // Drag events don't bubble - we're really just dragging the element, | 854 // Drag events don't bubble - we're really just dragging the element, |
856 // not affecting its parent at all. | 855 // not affecting its parent at all. |
857 var bubbles = !isDrag; | 856 var bubbles = !isDrag; |
858 | 857 |
859 var event = new TouchHandler.Event(eventType, bubbles, clientX, clientY, | 858 var event = new TouchHandler.Event( |
860 touchedElement); | 859 eventType, bubbles, clientX, clientY, touchedElement); |
861 | 860 |
862 // Set enableDrag when it can be overridden | 861 // Set enableDrag when it can be overridden |
863 if (eventType == TouchHandler.EventType.TOUCH_START) | 862 if (eventType == TouchHandler.EventType.TOUCH_START) |
864 event.enableDrag = false; | 863 event.enableDrag = false; |
865 else if (eventType == TouchHandler.EventType.DRAG_START) | 864 else if (eventType == TouchHandler.EventType.DRAG_START) |
866 event.enableDrag = true; | 865 event.enableDrag = true; |
867 | 866 |
868 if (isDrag) { | 867 if (isDrag) { |
869 event.dragDeltaX = clientX - this.startTouchX_; | 868 event.dragDeltaX = clientX - this.startTouchX_; |
870 event.dragDeltaY = clientY - this.startTouchY_; | 869 event.dragDeltaY = clientY - this.startTouchY_; |
871 } | 870 } |
872 | 871 |
873 this.element_.dispatchEvent(event); | 872 this.element_.dispatchEvent(event); |
874 return event.enableDrag; | 873 return event.enableDrag; |
875 } | 874 } |
876 }; | 875 }; |
877 | 876 |
878 return { | 877 return {TouchHandler: TouchHandler}; |
879 TouchHandler: TouchHandler | |
880 }; | |
881 }); | 878 }); |
OLD | NEW |