├── LICENSE ├── README.mkdn └── lib └── jquery.doubletap.js /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-* rick olson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | # DoubleTap for jQuery 2 | 3 | "One bullet more in the head will go a long way to ensuring your survival" - Zombieland 4 | 5 | DEMO: http://technoweenie.github.com/jquery.doubletap/ 6 | 7 | This plugin adds custom touch-screen events to the given HTML elements. This should only work on iPads, iPhones, and iPod Touches. Anything else is bonus. 8 | 9 | The simplest way to use this is to pass in a single callback. 10 | 11 | $('.swipe').addSwipeEvents(function(evt, touch) { 12 | // this is triggered for any of the custom touch events 13 | }); 14 | 15 | Or, you can bind to each custom event explicitly. 16 | 17 | $('.swipe').addSwipeEvents(). 18 | bind('swipe', function(evt, touch) { 19 | // triggered for swipe events 20 | }) 21 | 22 | The events that are triggered are: 23 | 24 | * touch (triggered for all events) 25 | * swipe (triggered for all swipe events) 26 | * tap (no horizontal or vertical movement) 27 | * doubletap 28 | * swipeleft 29 | * swiperight 30 | * swipeup 31 | * swipedown 32 | 33 | Each event passes an extra `touchStatus` object with these properties: 34 | 35 | * target (the HTML element triggering the event) 36 | * touch (a reference to the browser's TouchStatus object) 37 | * eventType (the name of the triggered event) 38 | * startX (the starting screenX value) 39 | * startY (the starting screenY value) 40 | * currentX (the latest screenX value) 41 | * currentY (the latest screenY value) 42 | 43 | ## TODO 44 | 45 | * Android support would rock :) 46 | * Gestures 47 | * Multi-finger swipes 48 | 49 | ## Acknowledgements 50 | 51 | * Ryan Scherf, author of the [swipe plugin][swipe] 52 | * nroberts, author of the [Touching and Gesturing on the iPhone][blog] blog post. 53 | 54 | [swipe]: http://plugins.jquery.com/project/swipe 55 | [blog]: http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/ 56 | 57 | ## Note on Patches/Pull Requests 58 | 59 | * Fork the project. 60 | * Make your feature addition or bug fix. 61 | * Commit, do not mess with version or history. 62 | (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) 63 | * Send me a pull request. Bonus points for topic branches. 64 | 65 | ## Copyright 66 | 67 | Copyright (c) 2010 rick. See LICENSE for details. 68 | -------------------------------------------------------------------------------- /lib/jquery.doubletap.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | var defaults = { 4 | 'swipeTolerance': 40 5 | }; 6 | 7 | var touchStatus = function(target, touch) { 8 | this.target = $(target); 9 | this.touch = touch; 10 | this.startX = this.currentX = touch.screenX; 11 | this.startY = this.currentY = touch.screenY; 12 | this.eventType = null; 13 | } 14 | touchStatus.options = {}; 15 | touchStatus.latestTap = null; 16 | 17 | touchStatus.prototype.move = function(touch) { 18 | this.currentX = touch.screenX; 19 | this.currentY = touch.screenY; 20 | } 21 | 22 | touchStatus.prototype.process = function() { 23 | var offsetX = this.currentX - this.startX; 24 | var offsetY = this.currentY - this.startY; 25 | if(offsetX == 0 && offsetY == 0) { 26 | this.checkForDoubleTap(); 27 | } else if(Math.abs(offsetY) > touchStatus.options.swipeTolerance && Math.abs(offsetY) > Math.abs(offsetX)) { 28 | this.eventType = offsetY > 0 ? 'swipedown' : 'swipeup'; 29 | this.target.trigger('swipe', [this]) 30 | } else if(Math.abs(offsetX) > touchStatus.options.swipeTolerance) { 31 | this.eventType = offsetX > 0 ? 'swiperight' : 'swipeleft'; 32 | this.target.trigger('swipe', [this]) 33 | } 34 | if(this.eventType) this.target.trigger(this.eventType, [this]) 35 | this.target.trigger('touch', [this]) 36 | } 37 | 38 | touchStatus.prototype.checkForDoubleTap = function() { 39 | if(touchStatus.latestTap) { 40 | if((new Date() - touchStatus.latestTap) < 400) 41 | this.eventType = 'doubletap' 42 | } 43 | if(!this.eventType) this.eventType = 'tap' 44 | touchStatus.latestTap = new Date() 45 | } 46 | 47 | var swipeEvents = function(elements, options) { 48 | touchStatus.options = $.extend(defaults, options); 49 | elements.bind('touchstart', this.touchStart); 50 | elements.bind('touchmove', this.touchMove); 51 | elements.bind('touchcancel', this.touchCancel); 52 | elements.bind('touchend', this.touchEnd); 53 | } 54 | 55 | swipeEvents.prototype.touchStart = function(evt) { 56 | var target = this; 57 | swipeEvents.eachTouch(evt, function(touch) { 58 | swipeEvents.touches[touch.identifier] = new touchStatus(target, touch); 59 | }) 60 | } 61 | 62 | swipeEvents.prototype.touchMove = function(evt) { 63 | swipeEvents.eachTouch(evt, function(touch) { 64 | var loc = swipeEvents.touches[touch.identifier] 65 | if(loc) loc.move(touch) 66 | }) 67 | } 68 | 69 | swipeEvents.prototype.touchCancel = function(evt) { 70 | swipeEvents.eachTouch(evt, function(touch) { 71 | swipeEvents.purge(touch, true) 72 | }) 73 | } 74 | 75 | swipeEvents.prototype.touchEnd = function(evt) { 76 | swipeEvents.eachTouch(evt, function(touch) { 77 | swipeEvents.purge(touch) 78 | }) 79 | } 80 | 81 | swipeEvents.touches = {} 82 | swipeEvents.purge = function(touch, cancelled) { 83 | if(!cancelled) { 84 | var loc = swipeEvents.touches[touch.identifier] 85 | if(loc) loc.process() 86 | } 87 | delete swipeEvents.touches[touch.identifier] 88 | } 89 | 90 | swipeEvents.eachTouch = function(evt, callback) { 91 | var evt = evt.originalEvent; 92 | var num = evt.changedTouches.length; 93 | for(var i = 0; i < num; i++) { 94 | callback(evt.changedTouches[i]) 95 | } 96 | } 97 | 98 | // adds custom events: 99 | // touch // all events 100 | // swipe // only swipe* events 101 | // swipeleft 102 | // swiperight 103 | // swipeup 104 | // swipedown 105 | // tap 106 | // doubletap 107 | $.fn.addSwipeEvents = function(options, callback) { 108 | if (!callback && jQuery.isFunction(options)) { 109 | callback = options; 110 | options = null; 111 | } 112 | new swipeEvents(this, options); 113 | if(callback) this.bind('touch', callback); 114 | return this; 115 | } 116 | })(jQuery); --------------------------------------------------------------------------------