[29468] | 1 | /**
|
---|
| 2 | * Copyright (c) 2011 Zauber S.A. <http://www.zaubersoftware.com/>
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
| 5 | * you may not use this file except in compliance with the License.
|
---|
| 6 | * You may obtain a copy of the License at
|
---|
| 7 | *
|
---|
| 8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
| 9 | *
|
---|
| 10 | * Unless required by applicable law or agreed to in writing, software
|
---|
| 11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
| 13 | * See the License for the specific language governing permissions and
|
---|
| 14 | * limitations under the License.
|
---|
| 15 | *
|
---|
| 16 | * @author Guido Marucci Blas - [email protected]
|
---|
| 17 | * @description Adds a handler for a custom event 'taphold' that handles a
|
---|
| 18 | * tap and hold on touch interfaces.
|
---|
| 19 | */
|
---|
| 20 | (function($) {
|
---|
| 21 | var TAP_AND_HOLD_TRIGGER_TIMER = 1000;
|
---|
| 22 | var MAX_DISTANCE_ALLOWED_IN_TAP_AND_HOLD_EVENT = 5;
|
---|
| 23 | var TOUCHSTART = "touchstart";
|
---|
| 24 | var TOUCHEND = "touchend";
|
---|
| 25 | var TOUCHMOVE = "touchmove";
|
---|
| 26 |
|
---|
| 27 | // For debugging only
|
---|
| 28 | // var TOUCHSTART = "mousedown";
|
---|
| 29 | // var TOUCHEND = "mouseup";
|
---|
| 30 | // var TOUCHMOVE = "mousemove";
|
---|
| 31 |
|
---|
| 32 | var tapAndHoldTimer = null;
|
---|
| 33 |
|
---|
| 34 | function calculateEuclideanDistance(x1, y1, x2, y2) {
|
---|
| 35 | var diffX = (x2 - x1);
|
---|
| 36 | var diffY = (y2 - y1);
|
---|
| 37 | return Math.sqrt((diffX * diffX) + (diffY * diffY));
|
---|
| 38 | };
|
---|
| 39 |
|
---|
| 40 | function onTouchStart(event) {
|
---|
| 41 | var e = event.originalEvent;
|
---|
| 42 |
|
---|
| 43 | // Only start detector if and only if one finger is over the widget
|
---|
| 44 | if (!e.touches || (e.targetTouches.length === 1 && e.touches.length === 1)) {
|
---|
| 45 | startTapAndHoldDetector.call(this, event)
|
---|
| 46 | var element = $(this);
|
---|
| 47 | element.bind(TOUCHMOVE, onTouchMove);
|
---|
| 48 | element.bind(TOUCHEND, onTouchEnd);
|
---|
| 49 | } else {
|
---|
| 50 | stopTapAndHoldDetector.call(this);
|
---|
| 51 | }
|
---|
| 52 | };
|
---|
| 53 |
|
---|
| 54 | function onTouchMove(event) {
|
---|
| 55 | if (tapAndHoldTimer == null) {
|
---|
| 56 | return;
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 | var e = event.originalEvent;
|
---|
| 60 | var x = (e.changedTouches) ? e.changedTouches[0].pageX: e.pageX;
|
---|
| 61 | var y = (e.changedTouches) ? e.changedTouches[0].pageY: e.pageY;
|
---|
| 62 |
|
---|
| 63 | var tapAndHoldPoint = $(this).data("taphold.point");
|
---|
| 64 | var euclideanDistance = calculateEuclideanDistance(tapAndHoldPoint.x, tapAndHoldPoint.y, x, y);
|
---|
| 65 |
|
---|
| 66 | if (euclideanDistance > MAX_DISTANCE_ALLOWED_IN_TAP_AND_HOLD_EVENT) {
|
---|
| 67 | stopTapAndHoldDetector.call(this);
|
---|
| 68 | }
|
---|
| 69 | };
|
---|
| 70 |
|
---|
| 71 | function onTouchEnd(event) {
|
---|
| 72 | stopTapAndHoldDetector.call(this);
|
---|
| 73 | };
|
---|
| 74 |
|
---|
| 75 | function onTapAndHold(event) {
|
---|
| 76 | clear.call(this);
|
---|
| 77 | $(this).data("taphold.handler").call(this, event);
|
---|
| 78 | };
|
---|
| 79 |
|
---|
| 80 | function clear() {
|
---|
| 81 | tapAndHoldTimer = null;
|
---|
| 82 | $(this).unbind(TOUCHMOVE, onTouchMove);
|
---|
| 83 | $(this).unbind(TOUCHEND, onTouchEnd);
|
---|
| 84 | };
|
---|
| 85 |
|
---|
| 86 | function startTapAndHoldDetector(event) {
|
---|
| 87 | if (tapAndHoldTimer != null) {
|
---|
| 88 | return;
|
---|
| 89 | }
|
---|
| 90 | var self = this;
|
---|
| 91 | tapAndHoldTimer = setTimeout(function(){
|
---|
| 92 | onTapAndHold.call(self, event)
|
---|
| 93 | }, TAP_AND_HOLD_TRIGGER_TIMER);
|
---|
| 94 |
|
---|
| 95 | // Stores tap x & y
|
---|
| 96 | var e = event.originalEvent;
|
---|
| 97 | var tapAndHoldPoint = {};
|
---|
| 98 | tapAndHoldPoint.x = (e.changedTouches) ? e.changedTouches[0].pageX: e.pageX;
|
---|
| 99 | tapAndHoldPoint.y = (e.changedTouches) ? e.changedTouches[0].pageY: e.pageY;
|
---|
| 100 | $(this).data("taphold.point", tapAndHoldPoint);
|
---|
| 101 | };
|
---|
| 102 |
|
---|
| 103 | function stopTapAndHoldDetector() {
|
---|
| 104 | clearTimeout(tapAndHoldTimer);
|
---|
| 105 | clear.call(this);
|
---|
| 106 | };
|
---|
| 107 |
|
---|
| 108 | $.event.special["taphold"] = {
|
---|
| 109 | setup: function() {
|
---|
| 110 |
|
---|
| 111 | },
|
---|
| 112 |
|
---|
| 113 | add: function(handleObj) {
|
---|
| 114 | $(this).data("taphold.handler", handleObj.handler);
|
---|
| 115 | if (handleObj.data) {
|
---|
| 116 | $(this).bind(TOUCHSTART, handleObj.data, onTouchStart);
|
---|
| 117 | } else {
|
---|
| 118 | $(this).bind(TOUCHSTART, onTouchStart);
|
---|
| 119 | }
|
---|
| 120 | },
|
---|
| 121 |
|
---|
| 122 | remove: function(handleObj) {
|
---|
| 123 | stopTapAndHoldDetector.call(this);
|
---|
| 124 | if (handleObj.data) {
|
---|
| 125 | $(this).unbind(TOUCHSTART, handleObj.data, onTouchStart);
|
---|
| 126 | } else {
|
---|
| 127 | $(this).unbind(TOUCHSTART, onTouchStart);
|
---|
| 128 | }
|
---|
| 129 | },
|
---|
| 130 |
|
---|
| 131 | teardown: function() {
|
---|
| 132 |
|
---|
| 133 | }
|
---|
| 134 | };
|
---|
| 135 |
|
---|
| 136 | })(jQuery); |
---|