PageSourceSearch

https://www.onlinecarstereo.com/assets/dist/js/jquery.touchSwipe.js

js onlinecarstereo.com collected 2026-09-24 20:17:54 UTC 82,408 bytes, 2,112 lines download raw bytes

vendor: 8,270 bytes, lines 1-155
1/*!
2 * @fileOverview TouchSwipe - jQuery Plugin
3 * @version 1.6.18
4 *
5 * @author Matt Bryson http://www.github.com/mattbryson
6 * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
7 * @see http://labs.rampinteractive.co.uk/touchSwipe/
8 * @see http://plugins.jquery.com/project/touchSwipe
9 * @license
10 * Copyright (c) 2010-2015 Matt Bryson
11 * Dual licensed under the MIT or GPL Version 2 licenses.
12 *
13 */
14
15/*
16 *
17 * Changelog
18 * $Date: 2010-12-12 (Wed, 12 Dec 2010) $
19 * $version: 1.0.0
20 * $version: 1.0.1 - removed multibyte comments
21 *
22 * $Date: 2011-21-02 (Mon, 21 Feb 2011) $
23 * $version: 1.1.0 	- added allowPageScroll property to allow swiping and scrolling of page
24 *					- changed handler signatures so one handler can be used for multiple events
25 * $Date: 2011-23-02 (Wed, 23 Feb 2011) $
26 * $version: 1.2.0 	- added click handler. This is fired if the user simply clicks and does not swipe. The event object and click target are passed to handler.
27 *					- If you use the http://code.google.com/p/jquery-ui-for-ipad-and-iphone/ plugin, you can also assign jQuery mouse events to children of a touchSwipe object.
28 * $version: 1.2.1 	- removed console log!
29 *
30 * $version: 1.2.2 	- Fixed bug where scope was not preserved in callback methods.
31 *
32 * $Date: 2011-28-04 (Thurs, 28 April 2011) $
33 * $version: 1.2.4 	- Changed licence terms to be MIT or GPL inline with jQuery. Added check for support of touch events to stop non compatible browsers erroring.
34 *
35 * $Date: 2011-27-09 (Tues, 27 September 2011) $
36 * $version: 1.2.5 	- Added support for testing swipes with mouse on desktop browser (thanks to https://github.com/joelhy)
37 *
38 * $Date: 2012-14-05 (Mon, 14 May 2012) $
39 * $version: 1.2.6 	- Added timeThreshold between start and end touch, so user can ignore slow swipes (thanks to Mark Chase). Default is null, all swipes are detected
40 *
41 * $Date: 2012-05-06 (Tues, 05 June 2012) $
42 * $version: 1.2.7 	- Changed time threshold to have null default for backwards compatibility. Added duration param passed back in events, and refactored how time is handled.
43 *
44 * $Date: 2012-05-06 (Tues, 05 June 2012) $
45 * $version: 1.2.8 	- Added the possibility to return a value like null or false in the trigger callback. In that way we can control when the touch start/move should take effect or not (simply by returning in some cases return null; or return false;) This effects the ontouchstart/ontouchmove event.
46 *
47 * $Date: 2012-06-06 (Wed, 06 June 2012) $
48 * $version: 1.3.0 	- Refactored whole plugin to allow for methods to be executed, as well as exposed defaults for user override. Added 'enable', 'disable', and 'destroy' methods
49 *
50 * $Date: 2012-05-06 (Fri, 05 June 2012) $
51 * $version: 1.3.1 	- Bug fixes  - bind() with false as last argument is no longer supported in jQuery 1.6, also, if you just click, the duration is now returned correctly.
52 *
53 * $Date: 2012-29-07 (Sun, 29 July 2012) $
54 * $version: 1.3.2	- Added fallbackToMouseEvents option to NOT capture mouse events on non touch devices.
55 * 			- Added "all" fingers value to the fingers property, so any combination of fingers triggers the swipe, allowing event handlers to check the finger count
56 *
57 * $Date: 2012-09-08 (Thurs, 9 Aug 2012) $
58 * $version: 1.3.3	- Code tidy prep for min version
59 *
60 * $Date: 2012-04-10 (wed, 4 Oct 2012) $
61 * $version: 1.4.0	- Added pinch support, pinchIn and pinchOut
62 *
63 * $Date: 2012-11-10 (Thurs, 11 Oct 2012) $
64 * $version: 1.5.0	- Added excludedElements, a jquery selector that specifies child elements that do NOT trigger swipes. By default, this is .noSwipe
65 *
66 * $Date: 2012-22-10 (Mon, 22 Oct 2012) $
67 * $version: 1.5.1	- Fixed bug with jQuery 1.8 and trailing comma in excludedElements
68 *					- Fixed bug with IE and eventPreventDefault()
69 * $Date: 2013-01-12 (Fri, 12 Jan 2013) $
70 * $version: 1.6.0	- Fixed bugs with pinching, mainly when both pinch and swipe enabled, as well as adding time threshold for multifinger gestures, so releasing one finger beofre the other doesnt trigger as single finger gesture.
71 *					- made the demo site all static local HTML pages so they can be run locally by a developer
72 *					- added jsDoc comments and added documentation for the plugin
73 *					- code tidy
74 *					- added triggerOnTouchLeave property that will end the event when the user swipes off the element.
75 * $Date: 2013-03-23 (Sat, 23 Mar 2013) $
76 * $version: 1.6.1	- Added support for ie8 touch events
77 * $version: 1.6.2	- Added support for events binding with on / off / bind in jQ for all callback names.
78 *                   - Deprecated the 'click' handler in favour of tap.
79 *                   - added cancelThreshold property
80 *                   - added option method to update init options at runtime
81 * $version 1.6.3    - added doubletap, longtap events and longTapThreshold, doubleTapThreshold property
82 *
83 * $Date: 2013-04-04 (Thurs, 04 April 2013) $
84 * $version 1.6.4    - Fixed bug with cancelThreshold introduced in 1.6.3, where swipe status no longer fired start event, and stopped once swiping back.
85 *
86 * $Date: 2013-08-24 (Sat, 24 Aug 2013) $
87 * $version 1.6.5    - Merged a few pull requests fixing various bugs, added AMD support.
88 *
89 * $Date: 2014-06-04 (Wed, 04 June 2014) $
90 * $version 1.6.6 	- Merge of pull requests.
91 *    				- IE10 touch support
92 *    				- Only prevent default event handling on valid swipe
93 *    				- Separate license/changelog comment
94 *    				- Detect if the swipe is valid at the end of the touch event.
95 *    				- Pass fingerdata to event handlers.
96 *    				- Add 'hold' gesture
97 *    				- Be more tolerant about the tap distance
98 *    				- Typos and minor fixes
99 *
100 * $Date: 2015-22-01 (Thurs, 22 Jan 2015) $
101 * $version 1.6.7    - Added patch from https://github.com/mattbryson/TouchSwipe-Jquery-Plugin/issues/206 to fix memory leak
102 *
103 * $Date: 2015-2-2 (Mon, 2 Feb 2015) $
104 * $version 1.6.8    - Added preventDefaultEvents option to proxy events regardless.
105 *					- Fixed issue with swipe and pinch not triggering at the same time
106 *
107 * $Date: 2015-9-6 (Tues, 9 June 2015) $
108 * $version 1.6.9    - Added PR from jdalton/hybrid to fix pointer events
109 *					- Added scrolling demo
110 *					- Added version property to plugin
111 *
112 * $Date: 2015-1-10 (Wed, 1 October 2015) $
113 * $version 1.6.10    - Added PR from beatspace to fix tap events
114 * $version 1.6.11    - Added PRs from indri-indri ( Doc tidyup), kkirsche ( Bower tidy up ), UziTech (preventDefaultEvents fixes )
115 *					 - Allowed setting multiple options via .swipe("options", options_hash) and more simply .swipe(options_hash) or exisitng instances
116 * $version 1.6.12    - Fixed bug with multi finger releases above 2 not triggering events
117 *
118 * $Date: 2015-12-18 (Fri, 18 December 2015) $
119 * $version 1.6.13    - Added PRs
120 *                    - Fixed #267 allowPageScroll not working correctly
121 * $version 1.6.14    - Fixed #220 / #248 doubletap not firing with swipes, #223 commonJS compatible
122 * $version 1.6.15    - More bug fixes
123 *
124 * $Date: 2016-04-29 (Fri, 29 April 2016) $
125 * $version 1.6.16    - Swipes with 0 distance now allow default events to trigger.  So tapping any form elements or A tags will allow default interaction, but swiping will trigger a swipe.
126 *                       Removed the a, input, select etc from the excluded Children list as the 0 distance tap solves that issue.
127 * $Date: 2016-05-19  (Fri, 29 April 2016) $
128 * $version 1.6.17     - Fixed context issue when calling instance methods via $("selector").swipe("method");
129 * $version 1.6.18     - now honors fallbackToMouseEvents=false for MS Pointer events when a Mouse is used.
130 * 
131 * $Date: 2018-09-17  (Mon, 17 September 2018) $
132 * $version 1.6.19     - replaced jQuery bind with on, replaced deprecated `navigator.pointerEvents` with `window.PointerEvents`
133
134 */
135
136/**
137 * See (http://jquery.com/).
138 * @name $
139 * @class
140 * See the jQuery Library  (http://jquery.com/) for full details.  This just
141 * documents the function and classes that are added to jQuery by this plug-in.
142 */
143
144/**
145 * See (http://jquery.com/)
146 * @name fn
147 * @class
148 * See the jQuery Library  (http://jquery.com/) for full details.  This just
149 * documents the function and classes that are added to jQuery by this plug-in.
150 * @memberOf $
151 */
152
153
154(function(factory) {
155  
vendor: 68,601 bytes, lines 155-1998
155  if (typeof define === 'function' && define.amd && define.amd.jQuery) {
156      // AMD. Register as anonymous module.
157      define(['jquery'], factory);
158    } else if (typeof module !== 'undefined' && module.exports) {
159      // CommonJS Module
160      factory(require("jquery"));
161    } else {
162      // Browser globals.
163      factory(jQuery);
164    }
165  }(function($) {
166    "use strict";
167  
168    //Constants
169    var VERSION = "1.6.18",
170      LEFT = "left",
171      RIGHT = "right",
172      UP = "up",
173      DOWN = "down",
174      IN = "in",
175      OUT = "out",
176  
177      NONE = "none",
178      AUTO = "auto",
179  
180      SWIPE = "swipe",
181      PINCH = "pinch",
182      TAP = "tap",
183      DOUBLE_TAP = "doubletap",
184      LONG_TAP = "longtap",
185      HOLD = "hold",
186  
187      HORIZONTAL = "horizontal",
188      VERTICAL = "vertical",
189  
190      ALL_FINGERS = "all",
191  
192      DOUBLE_TAP_THRESHOLD = 10,
193  
194      PHASE_START = "start",
195      PHASE_MOVE = "move",
196      PHASE_END = "end",
197      PHASE_CANCEL = "cancel",
198  
199      SUPPORTS_TOUCH = 'ontouchstart' in window,
200  
201      SUPPORTS_POINTER_IE10 = window.navigator.msPointerEnabled && !window.PointerEvent && !SUPPORTS_TOUCH,
202  
203      SUPPORTS_POINTER = (window.PointerEvent || window.navigator.msPointerEnabled) && !SUPPORTS_TOUCH,
204  
205      PLUGIN_NS = 'TouchSwipe';
206  
207  
208  
209    /**
210    * The default configuration, and available options to configure touch swipe with.
211    * You can set the default values by updating any of the properties prior to instantiation.
212    * @name $.fn.swipe.defaults
213    * @namespace
214    * @property {int} [fingers=1] The number of fingers to detect in a swipe. Any swipes that do not meet this requirement will NOT trigger swipe handlers.
215    * @property {int} [threshold=75] The number of pixels that the user must move their finger by before it is considered a swipe.
216    * @property {int} [cancelThreshold=null] The number of pixels that the user must move their finger back from the original swipe direction to cancel the gesture.
217    * @property {int} [pinchThreshold=20] The number of pixels that the user must pinch their finger by before it is considered a pinch.
218    * @property {int} [maxTimeThreshold=null] Time, in milliseconds, between touchStart and touchEnd must NOT exceed in order to be considered a swipe.
219    * @property {int} [fingerReleaseThreshold=250] Time in milliseconds between releasing multiple fingers.  If 2 fingers are down, and are released one after the other, if they are within this threshold, it counts as a simultaneous release.
220    * @property {int} [longTapThreshold=500] Time in milliseconds between tap and release for a long tap
221    * @property {int} [doubleTapThreshold=200] Time in milliseconds between 2 taps to count as a double tap
222    * @property {function} [swipe=null] A handler to catch all swipes. See {@link $.fn.swipe#event:swipe}
223    * @property {function} [swipeLeft=null] A handler that is triggered for "left" swipes. See {@link $.fn.swipe#event:swipeLeft}
224    * @property {function} [swipeRight=null] A handler that is triggered for "right" swipes. See {@link $.fn.swipe#event:swipeRight}
225    * @property {function} [swipeUp=null] A handler that is triggered for "up" swipes. See {@link $.fn.swipe#event:swipeUp}
226    * @property {function} [swipeDown=null] A handler that is triggered for "down" swipes. See {@link $.fn.swipe#event:swipeDown}
227    * @property {function} [swipeStatus=null] A handler triggered for every phase of the swipe. See {@link $.fn.swipe#event:swipeStatus}
228    * @property {function} [pinchIn=null] A handler triggered for pinch in events. See {@link $.fn.swipe#event:pinchIn}
229    * @property {function} [pinchOut=null] A handler triggered for pinch out events. See {@link $.fn.swipe#event:pinchOut}
230    * @property {function} [pinchStatus=null] A handler triggered for every phase of a pinch. See {@link $.fn.swipe#event:pinchStatus}
231    * @property {function} [tap=null] A handler triggered when a user just taps on the item, rather than swipes it. If they do not move, tap is triggered, if they do move, it is not.
232    * @property {function} [doubleTap=null] A handler triggered when a user double taps on the item. The delay between taps can be set with the doubleTapThreshold property. See {@link $.fn.swipe.defaults#doubleTapThreshold}
233    * @property {function} [longTap=null] A handler triggered when a user long taps on the item. The delay between start and end can be set with the longTapThreshold property. See {@link $.fn.swipe.defaults#longTapThreshold}
234    * @property (function) [hold=null] A handler triggered when a user reaches longTapThreshold on the item. See {@link $.fn.swipe.defaults#longTapThreshold}
235    * @property {boolean} [triggerOnTouchEnd=true] If true, the swipe events are triggered when the touch end event is received (user releases finger).  If false, it will be triggered on reaching the threshold, and then cancel the touch event automatically.
236    * @property {boolean} [triggerOnTouchLeave=false] If true, then when the user leaves the swipe object, the swipe will end and trigger appropriate handlers.
237    * @property {string|undefined} [allowPageScroll='auto'] How the browser handles page scrolls when the user is swiping on a touchSwipe object. See {@link $.fn.swipe.pageScroll}.  <br/><br/>
238                      <code>"auto"</code> : all undefined swipes will cause the page to scroll in that direction. <br/>
239                      <code>"none"</code> : the page will not scroll when user swipes. <br/>
240                      <code>"horizontal"</code> : will force page to scroll on horizontal swipes. <br/>
241                      <code>"vertical"</code> : will force page to scroll on vertical swipes. <br/>
242    * @property {boolean} [fallbackToMouseEvents=true] If true mouse events are used when run on a non touch device, false will stop swipes being triggered by mouse events on non touch devices.
243    * @property {string} [excludedElements=".noSwipe"] A jquery selector that specifies child elements that do NOT trigger swipes. By default this excludes elements with the class .noSwipe .
244    * @property {boolean} [preventDefaultEvents=true] by default default events are cancelled, so the page doesn't move.  You can disable this so both native events fire as well as your handlers.
245  
246    */
247    var defaults = {
248      fingers: 1,
249      threshold: 75,
250      cancelThreshold: null,
251      pinchThreshold: 20,
252      maxTimeThreshold: null,
253      fingerReleaseThreshold: 250,
254      longTapThreshold: 500,
255      doubleTapThreshold: 200,
256      swipe: null,
257      swipeLeft: null,
258      swipeRight: null,
259      swipeUp: null,
260      swipeDown: null,
261      swipeStatus: null,
262      pinchIn: null,
263      pinchOut: null,
264      pinchStatus: null,
265      click: null, //Deprecated since 1.6.2
266      tap: null,
267      doubleTap: null,
268      longTap: null,
269      hold: null,
270      triggerOnTouchEnd: true,
271      triggerOnTouchLeave: false,
272      allowPageScroll: "auto",
273      fallbackToMouseEvents: true,
274      excludedElements: ".noSwipe",
275      preventDefaultEvents: true
276    };
277  
278  
279  
280    /**
281     * Applies TouchSwipe behaviour to one or more jQuery objects.
282     * The TouchSwipe plugin can be instantiated via this method, or methods within
283     * TouchSwipe can be executed via this method as per jQuery plugin architecture.
284     * An existing plugin can have its options changed simply by re calling .swipe(options)
285     * @see TouchSwipe
286     * @class
287     * @param {Mixed} method If the current DOMNode is a TouchSwipe object, and <code>method</code> is a TouchSwipe method, then
288     * the <code>method</code> is executed, and any following arguments are passed to the TouchSwipe method.
289     * If <code>method</code> is an object, then the TouchSwipe class is instantiated on the current DOMNode, passing the
290     * configuration properties defined in the object. See TouchSwipe
291     *
292     */
293    $.fn.swipe = function(method) {
294      var $this = $(this),
295        plugin = $this.data(PLUGIN_NS);
296  
297      //Check if we are already instantiated and trying to execute a method
298      if (plugin && typeof method === 'string') {
299        if (plugin[method]) {
300          return plugin[method].apply(plugin, Array.prototype.slice.call(arguments, 1));
301        } else {
302          $.error('Method ' + method + ' does not exist on jQuery.swipe');
303        }
304      }
305  
306      //Else update existing plugin with new options hash
307      else if (plugin && typeof method === 'object') {
308        plugin['option'].apply(plugin, arguments);
309      }
310  
311      //Else not instantiated and trying to pass init object (or nothing)
312      else if (!plugin && (typeof method === 'object' || !method)) {
313        return init.apply(this, arguments);
314      }
315  
316      return $this;
317    };
318  
319    /**
320     * The version of the plugin
321     * @readonly
322     */
323    $.fn.swipe.version = VERSION;
324  
325  
326  
327    //Expose our defaults so a user could override the plugin defaults
328    $.fn.swipe.defaults = defaults;
329  
330    /**
331     * The phases that a touch event goes through.  The <code>phase</code> is passed to the event handlers.
332     * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
333     * @namespace
334     * @readonly
335     * @property {string} PHASE_START Constant indicating the start phase of the touch event. Value is <code>"start"</code>.
336     * @property {string} PHASE_MOVE Constant indicating the move phase of the touch event. Value is <code>"move"</code>.
337     * @property {string} PHASE_END Constant indicating the end phase of the touch event. Value is <code>"end"</code>.
338     * @property {string} PHASE_CANCEL Constant indicating the cancel phase of the touch event. Value is <code>"cancel"</code>.
339     */
340    $.fn.swipe.phases = {
341      PHASE_START: PHASE_START,
342      PHASE_MOVE: PHASE_MOVE,
343      PHASE_END: PHASE_END,
344      PHASE_CANCEL: PHASE_CANCEL
345    };
346  
347    /**
348     * The direction constants that are passed to the event handlers.
349     * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
350     * @namespace
351     * @readonly
352     * @property {string} LEFT Constant indicating the left direction. Value is <code>"left"</code>.
353     * @property {string} RIGHT Constant indicating the right direction. Value is <code>"right"</code>.
354     * @property {string} UP Constant indicating the up direction. Value is <code>"up"</code>.
355     * @property {string} DOWN Constant indicating the down direction. Value is <code>"cancel"</code>.
356     * @property {string} IN Constant indicating the in direction. Value is <code>"in"</code>.
357     * @property {string} OUT Constant indicating the out direction. Value is <code>"out"</code>.
358     */
359    $.fn.swipe.directions = {
360      LEFT: LEFT,
361      RIGHT: RIGHT,
362      UP: UP,
363      DOWN: DOWN,
364      IN: IN,
365      OUT: OUT
366    };
367  
368    /**
369     * The page scroll constants that can be used to set the value of <code>allowPageScroll</code> option
370     * These properties are read only
371     * @namespace
372     * @readonly
373     * @see $.fn.swipe.defaults#allowPageScroll
374     * @property {string} NONE Constant indicating no page scrolling is allowed. Value is <code>"none"</code>.
375     * @property {string} HORIZONTAL Constant indicating horizontal page scrolling is allowed. Value is <code>"horizontal"</code>.
376     * @property {string} VERTICAL Constant indicating vertical page scrolling is allowed. Value is <code>"vertical"</code>.
377     * @property {string} AUTO Constant indicating either horizontal or vertical will be allowed, depending on the swipe handlers registered. Value is <code>"auto"</code>.
378     */
379    $.fn.swipe.pageScroll = {
380      NONE: NONE,
381      HORIZONTAL: HORIZONTAL,
382      VERTICAL: VERTICAL,
383      AUTO: AUTO
384    };
385  
386    /**
387     * Constants representing the number of fingers used in a swipe.  These are used to set both the value of <code>fingers</code> in the
388     * options object, as well as the value of the <code>fingers</code> event property.
389     * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
390     * @namespace
391     * @readonly
392     * @see $.fn.swipe.defaults#fingers
393     * @property {string} ONE Constant indicating 1 finger is to be detected / was detected. Value is <code>1</code>.
394     * @property {string} TWO Constant indicating 2 fingers are to be detected / were detected. Value is <code>2</code>.
395     * @property {string} THREE Constant indicating 3 finger are to be detected / were detected. Value is <code>3</code>.
396     * @property {string} FOUR Constant indicating 4 finger are to be detected / were detected. Not all devices support this. Value is <code>4</code>.
397     * @property {string} FIVE Constant indicating 5 finger are to be detected / were detected. Not all devices support this. Value is <code>5</code>.
398     * @property {string} ALL Constant indicating any combination of finger are to be detected.  Value is <code>"all"</code>.
399     */
400    $.fn.swipe.fingers = {
401      ONE: 1,
402      TWO: 2,
403      THREE: 3,
404      FOUR: 4,
405      FIVE: 5,
406      ALL: ALL_FINGERS
407    };
408  
409    /**
410     * Initialise the plugin for each DOM element matched
411     * This creates a new instance of the main TouchSwipe class for each DOM element, and then
412     * saves a reference to that instance in the elements data property.
413     * @internal
414     */
415    function init(options) {
416      //Prep and extend the options
417      if (options && (options.allowPageScroll === undefined && (options.swipe !== undefined || options.swipeStatus !== undefined))) {
418        options.allowPageScroll = NONE;
419      }
420  
421      //Check for deprecated options
422      //Ensure that any old click handlers are assigned to the new tap, unless we have a tap
423      if (options.click !== undefined && options.tap === undefined) {
424        options.tap = options.click;
425      }
426  
427      if (!options) {
428        options = {};
429      }
430  
431      //pass empty object so we dont modify the defaults
432      options = $.extend({}, $.fn.swipe.defaults, options);
433  
434      //For each element instantiate the plugin
435      return this.each(function() {
436        var $this = $(this);
437  
438        //Check we havent already initialised the plugin
439        var plugin = $this.data(PLUGIN_NS);
440  
441        if (!plugin) {
442          plugin = new TouchSwipe(this, options);
443          $this.data(PLUGIN_NS, plugin);
444        }
445      });
446    }
447  
448    /**
449     * Main TouchSwipe Plugin Class.
450     * Do not use this to construct your TouchSwipe object, use the jQuery plugin method $.fn.swipe(); {@link $.fn.swipe}
451     * @private
452     * @name TouchSwipe
453     * @param {DOMNode} element The HTML DOM object to apply to plugin to
454     * @param {Object} options The options to configure the plugin with.  @link {$.fn.swipe.defaults}
455     * @see $.fh.swipe.defaults
456     * @see $.fh.swipe
457     * @class
458     */
459    function TouchSwipe(element, options) {
460  
461      //take a local/instacne level copy of the options - should make it this.options really...
462      var options = $.extend({}, options);
463  
464      var useTouchEvents = (SUPPORTS_TOUCH || SUPPORTS_POINTER || !options.fallbackToMouseEvents),
465        START_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerDown' : 'pointerdown') : 'touchstart') : 'mousedown',
466        MOVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerMove' : 'pointermove') : 'touchmove') : 'mousemove',
467        END_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerUp' : 'pointerup') : 'touchend') : 'mouseup',
468        LEAVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? 'mouseleave' : null) : 'mouseleave', //we manually detect leave on touch devices, so null event here
469        CANCEL_EV = (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerCancel' : 'pointercancel') : 'touchcancel');
470  
471  
472  
473      //touch properties
474      var distance = 0,
475        direction = null,
476        currentDirection = null,
477        duration = 0,
478        startTouchesDistance = 0,
479        endTouchesDistance = 0,
480        pinchZoom = 1,
481        pinchDistance = 0,
482        pinchDirection = 0,
483        maximumsMap = null;
484  
485  
486  
487      //jQuery wrapped element for this instance
488      var $element = $(element);
489  
490      //Current phase of th touch cycle
491      var phase = "start";
492  
493      // the current number of fingers being used.
494      var fingerCount = 0;
495  
496      //track mouse points / delta
497      var fingerData = {};
498  
499      //track times
500      var startTime = 0,
501        endTime = 0,
502        previousTouchEndTime = 0,
503        fingerCountAtRelease = 0,
504        doubleTapStartTime = 0;
505  
506      //Timeouts
507      var singleTapTimeout = null,
508        holdTimeout = null;
509  
510      // Add gestures to all swipable areas if supported
511      try {
512        $element.on(START_EV, touchStart);
513        $element.on(CANCEL_EV, touchCancel);
514      } catch (e) {
515        $.error('events not supported ' + START_EV + ',' + CANCEL_EV + ' on jQuery.swipe');
516      }
517  
518      //
519      //Public methods
520      //
521  
522      /**
523       * re-enables the swipe plugin with the previous configuration
524       * @function
525       * @name $.fn.swipe#enable
526       * @return {DOMNode} The Dom element that was registered with TouchSwipe
527       * @example $("#element").swipe("enable");
528       */
529      this.enable = function() {
530        //Incase we are already enabled, clean up...
531        this.disable();
532        $element.on(START_EV, touchStart);
533        $element.on(CANCEL_EV, touchCancel);
534        return $element;
535      };
536  
537      /**
538       * disables the swipe plugin
539       * @function
540       * @name $.fn.swipe#disable
541       * @return {DOMNode} The Dom element that is now registered with TouchSwipe
542       * @example $("#element").swipe("disable");
543       */
544      this.disable = function() {
545        removeListeners();
546        return $element;
547      };
548  
549      /**
550       * Destroy the swipe plugin completely. To use any swipe methods, you must re initialise the plugin.
551       * @function
552       * @name $.fn.swipe#destroy
553       * @example $("#element").swipe("destroy");
554       */
555      this.destroy = function() {
556        removeListeners();
557        $element.data(PLUGIN_NS, null);
558        $element = null;
559      };
560  
561  
562      /**
563       * Allows run time updating of the swipe configuration options.
564       * @function
565       * @name $.fn.swipe#option
566       * @param {String} property The option property to get or set, or a has of multiple options to set
567       * @param {Object} [value] The value to set the property to
568       * @return {Object} If only a property name is passed, then that property value is returned. If nothing is passed the current options hash is returned.
569       * @example $("#element").swipe("option", "threshold"); // return the threshold
570       * @example $("#element").swipe("option", "threshold", 100); // set the threshold after init
571       * @example $("#element").swipe("option", {threshold:100, fingers:3} ); // set multiple properties after init
572       * @example $("#element").swipe({threshold:100, fingers:3} ); // set multiple properties after init - the "option" method is optional!
573       * @example $("#element").swipe("option"); // Return the current options hash
574       * @see $.fn.swipe.defaults
575       *
576       */
577      this.option = function(property, value) {
578  
579        if (typeof property === 'object') {
580          options = $.extend(options, property);
581        } else if (options[property] !== undefined) {
582          if (value === undefined) {
583            return options[property];
584          } else {
585            options[property] = value;
586          }
587        } else if (!property) {
588          return options;
589        } else {
590          $.error('Option ' + property + ' does not exist on jQuery.swipe.options');
591        }
592  
593        return null;
594      }
595  
596  
597  
598      //
599      // Private methods
600      //
601  
602      //
603      // EVENTS
604      //
605      /**
606       * Event handler for a touch start event.
607       * Stops the default click event from triggering and stores where we touched
608       * @inner
609       * @param {object} jqEvent The normalised jQuery event object.
610       */
611      function touchStart(jqEvent) {
612  
613        //If we already in a touch event (a finger already in use) then ignore subsequent ones..
614        if (getTouchInProgress()) {
615          return;
616        }
617  
618        //Check if this element matches any in the excluded elements selectors,  or its parent is excluded, if so, DON'T swipe
619        if ($(jqEvent.target).closest(options.excludedElements, $element).length > 0) {
620          return;
621        }
622  
623        //As we use Jquery bind for events, we need to target the original event object
624        //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
625        var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
626  
627  
628        //If we have a pointer event, whoes type is 'mouse' and we have said NO mouse events, then dont do anything.
629        if(event.pointerType && event.pointerType=="mouse" && options.fallbackToMouseEvents==false) {
630          return;
631        };
632  
633        var ret,
634          touches = event.touches,
635          evt = touches ? touches[0] : event;
636  
637        phase = PHASE_START;
638  
639        //If we support touches, get the finger count
640        if (touches) {
641          // get the total number of fingers touching the screen
642          fingerCount = touches.length;
643        }
644        //Else this is the desktop, so stop the browser from dragging content
645        else if (options.preventDefaultEvents !== false) {
646          jqEvent.preventDefault(); //call this on jq event so we are cross browser
647        }
648  
649        //clear vars..
650        distance = 0;
651        direction = null;
652        currentDirection=null;
653        pinchDirection = null;
654        duration = 0;
655        startTouchesDistance = 0;
656        endTouchesDistance = 0;
657        pinchZoom = 1;
658        pinchDistance = 0;
659        maximumsMap = createMaximumsData();
660        cancelMultiFingerRelease();
661  
662        //Create the default finger data
663        createFingerData(0, evt);
664  
665        // check the number of fingers is what we are looking for, or we are capturing pinches
666        if (!touches || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
667          // get the coordinates of the touch
668          startTime = getTimeStamp();
669  
670          if (fingerCount == 2) {
671            //Keep track of the initial pinch distance, so we can calculate the diff later
672            //Store second finger data as start
673            createFingerData(1, touches[1]);
674            startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
675          }
676  
677          if (options.swipeStatus || options.pinchStatus) {
678            ret = triggerHandler(event, phase);
679          }
680        } else {
681          //A touch with more or less than the fingers we are looking for, so cancel
682          ret = false;
683        }
684  
685        //If we have a return value from the users handler, then return and cancel
686        if (ret === false) {
687          phase = PHASE_CANCEL;
688          triggerHandler(event, phase);
689          return ret;
690        } else {
691          if (options.hold) {
692            holdTimeout = setTimeout($.proxy(function() {
693              //Trigger the event
694              $element.trigger('hold', [event.target]);
695              //Fire the callback
696              if (options.hold) {
697                ret = options.hold.call($element, event, event.target);
698              }
699            }, this), options.longTapThreshold);
700          }
701  
702          setTouchInProgress(true);
703        }
704  
705        return null;
706      };
707  
708  
709  
710      /**
711       * Event handler for a touch move event.
712       * If we change fingers during move, then cancel the event
713       * @inner
714       * @param {object} jqEvent The normalised jQuery event object.
715       */
716      function touchMove(jqEvent) {
717  
718        //As we use Jquery bind for events, we need to target the original event object
719        //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
720        var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
721  
722        //If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
723        if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
724          return;
725  
726        var ret,
727          touches = event.touches,
728          evt = touches ? touches[0] : event;
729  
730  
731        //Update the  finger data
732        var currentFinger = updateFingerData(evt);
733        endTime = getTimeStamp();
734  
735        if (touches) {
736          fingerCount = touches.length;
737        }
738  
739        if (options.hold) {
740          clearTimeout(holdTimeout);
741        }
742  
743        phase = PHASE_MOVE;
744  
745        //If we have 2 fingers get Touches distance as well
746        if (fingerCount == 2) {
747  
748          //Keep track of the initial pinch distance, so we can calculate the diff later
749          //We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
750          if (startTouchesDistance == 0) {
751            //Create second finger if this is the first time...
752            createFingerData(1, touches[1]);
753  
754            startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
755          } else {
756            //Else just update the second finger
757            updateFingerData(touches[1]);
758  
759            endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
760            pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
761          }
762  
763          pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
764          pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
765        }
766  
767        if ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !touches || hasPinches()) {
768  
769          //The overall direction of the swipe. From start to now.
770          direction = calculateDirection(currentFinger.start, currentFinger.end);
771  
772          //The immediate direction of the swipe, direction between the last movement and this one.
773          currentDirection = calculateDirection(currentFinger.last, currentFinger.end);
774  
775          //Check if we need to prevent default event (page scroll / pinch zoom) or not
776          validateDefaultEvent(jqEvent, currentDirection);
777  
778          //Distance and duration are all off the main finger
779          distance = calculateDistance(currentFinger.start, currentFinger.end);
780          duration = calculateDuration();
781  
782          //Cache the maximum distance we made in this direction
783          setMaxDistance(direction, distance);
784  
785          //Trigger status handler
786          ret = triggerHandler(event, phase);
787  
788  
789          //If we trigger end events when threshold are met, or trigger events when touch leaves element
790          if (!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
791  
792            var inBounds = true;
793  
794            //If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
795            if (options.triggerOnTouchLeave) {
796              var bounds = getbounds(this);
797              inBounds = isInBounds(currentFinger.end, bounds);
798            }
799  
800            //Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
801            if (!options.triggerOnTouchEnd && inBounds) {
802              phase = getNextPhase(PHASE_MOVE);
803            }
804            //We end if out of bounds here, so set current phase to END, and check if its modified
805            else if (options.triggerOnTouchLeave && !inBounds) {
806              phase = getNextPhase(PHASE_END);
807            }
808  
809            if (phase == PHASE_CANCEL || phase == PHASE_END) {
810              triggerHandler(event, phase);
811            }
812          }
813        } else {
814          phase = PHASE_CANCEL;
815          triggerHandler(event, phase);
816        }
817  
818        if (ret === false) {
819          phase = PHASE_CANCEL;
820          triggerHandler(event, phase);
821        }
822      }
823  
824  
825  
826  
827      /**
828       * Event handler for a touch end event.
829       * Calculate the direction and trigger events
830       * @inner
831       * @param {object} jqEvent The normalised jQuery event object.
832       */
833      function touchEnd(jqEvent) {
834        //As we use Jquery bind for events, we need to target the original event object
835        //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
836        var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent,
837          touches = event.touches;
838  
839        //If we are still in a touch with the device wait a fraction and see if the other finger comes up
840        //if it does within the threshold, then we treat it as a multi release, not a single release and end the touch / swipe
841        if (touches) {
842          if (touches.length && !inMultiFingerRelease()) {
843            startMultiFingerRelease(event);
844            return true;
845          } else if (touches.length && inMultiFingerRelease()) {
846            return true;
847          }
848        }
849  
850        //If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
851        //This is used to allow 2 fingers to release fractionally after each other, whilst maintaining the event as containing 2 fingers, not 1
852        if (inMultiFingerRelease()) {
853          fingerCount = fingerCountAtRelease;
854        }
855  
856        //Set end of swipe
857        endTime = getTimeStamp();
858  
859        //Get duration incase move was never fired
860        duration = calculateDuration();
861  
862        //If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
863        if (didSwipeBackToCancel() || !validateSwipeDistance()) {
864          phase = PHASE_CANCEL;
865          triggerHandler(event, phase);
866        } else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd === false && phase === PHASE_MOVE)) {
867          //call this on jq event so we are cross browser
868          if (options.preventDefaultEvents !== false && jqEvent.cancelable !== false) {
869            jqEvent.preventDefault();
870          }
871          phase = PHASE_END;
872          triggerHandler(event, phase);
873        }
874        //Special cases - A tap should always fire on touch end regardless,
875        //So here we manually trigger the tap end handler by itself
876        //We dont run trigger handler as it will re-trigger events that may have fired already
877        else if (!options.triggerOnTouchEnd && hasTap()) {
878          //Trigger the pinch events...
879          phase = PHASE_END;
880          triggerHandlerForGesture(event, phase, TAP);
881        } else if (phase === PHASE_MOVE) {
882          phase = PHASE_CANCEL;
883          triggerHandler(event, phase);
884        }
885  
886        setTouchInProgress(false);
887  
888        return null;
889      }
890  
891  
892  
893      /**
894       * Event handler for a touch cancel event.
895       * Clears current vars
896       * @inner
897       */
898      function touchCancel() {
899        // reset the variables back to default values
900        fingerCount = 0;
901        endTime = 0;
902        startTime = 0;
903        startTouchesDistance = 0;
904        endTouchesDistance = 0;
905        pinchZoom = 1;
906  
907        //If we were in progress of tracking a possible multi touch end, then re set it.
908        cancelMultiFingerRelease();
909  
910        setTouchInProgress(false);
911      }
912  
913  
914      /**
915       * Event handler for a touch leave event.
916       * This is only triggered on desktops, in touch we work this out manually
917       * as the touchleave event is not supported in webkit
918       * @inner
919       */
920      function touchLeave(jqEvent) {
921        //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
922        var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
923  
924        //If we have the trigger on leave property set....
925        if (options.triggerOnTouchLeave) {
926          phase = getNextPhase(PHASE_END);
927          triggerHandler(event, phase);
928        }
929      }
930  
931      /**
932       * Removes all listeners that were associated with the plugin
933       * @inner
934       */
935      function removeListeners() {
936        $element.off(START_EV, touchStart);
937        $element.off(CANCEL_EV, touchCancel);
938        $element.off(MOVE_EV, touchMove);
939        $element.off(END_EV, touchEnd);
940  
941        //we only have leave events on desktop, we manually calculate leave on touch as its not supported in webkit
942        if (LEAVE_EV) {
943          $element.off(LEAVE_EV, touchLeave);
944        }
945  
946        setTouchInProgress(false);
947      }
948  
949  
950      /**
951       * Checks if the time and distance thresholds have been met, and if so then the appropriate handlers are fired.
952       */
953      function getNextPhase(currentPhase) {
954  
955        var nextPhase = currentPhase;
956  
957        // Ensure we have valid swipe (under time and over distance  and check if we are out of bound...)
958        var validTime = validateSwipeTime();
959        var validDistance = validateSwipeDistance();
960        var didCancel = didSwipeBackToCancel();
961  
962        //If we have exceeded our time, then cancel
963        if (!validTime || didCancel) {
964          nextPhase = PHASE_CANCEL;
965        }
966        //Else if we are moving, and have reached distance then end
967        else if (validDistance && currentPhase == PHASE_MOVE && (!options.triggerOnTouchEnd || options.triggerOnTouchLeave)) {
968          nextPhase = PHASE_END;
969        }
970        //Else if we have ended by leaving and didn't reach distance, then cancel
971        else if (!validDistance && currentPhase == PHASE_END && options.triggerOnTouchLeave) {
972          nextPhase = PHASE_CANCEL;
973        }
974  
975        return nextPhase;
976      }
977  
978  
979      /**
980       * Trigger the relevant event handler
981       * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
982       * @param {object} event the original event object
983       * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
984       * @inner
985       */
986      function triggerHandler(event, phase) {
987  
988  
989  
990        var ret,
991          touches = event.touches;
992  
993        // SWIPE GESTURES
994        if (didSwipe() || hasSwipes()) {
995            ret = triggerHandlerForGesture(event, phase, SWIPE);
996        }
997  
998        // PINCH GESTURES (if the above didn't cancel)
999        if ((didPinch() || hasPinches()) && ret !== false) {
1000            ret = triggerHandlerForGesture(event, phase, PINCH);
1001        }
1002  
1003        // CLICK / TAP (if the above didn't cancel)
1004        if (didDoubleTap() && ret !== false) {
1005          //Trigger the tap events...
1006          ret = triggerHandlerForGesture(event, phase, DOUBLE_TAP);
1007        }
1008  
1009        // CLICK / TAP (if the above didn't cancel)
1010        else if (didLongTap() && ret !== false) {
1011          //Trigger the tap events...
1012          ret = triggerHandlerForGesture(event, phase, LONG_TAP);
1013        }
1014  
1015        // CLICK / TAP (if the above didn't cancel)
1016        else if (didTap() && ret !== false) {
1017          //Trigger the tap event..
1018          ret = triggerHandlerForGesture(event, phase, TAP);
1019        }
1020  
1021  
1022  
1023        // If we are cancelling the gesture, then manually trigger the reset handler
1024        if (phase === PHASE_CANCEL) {
1025  
1026          touchCancel(event);
1027        }
1028  
1029  
1030  
1031  
1032        // If we are ending the gesture, then manually trigger the reset handler IF all fingers are off
1033        if (phase === PHASE_END) {
1034          //If we support touch, then check that all fingers are off before we cancel
1035          if (touches) {
1036            if (!touches.length) {
1037              touchCancel(event);
1038            }
1039          } else {
1040            touchCancel(event);
1041          }
1042        }
1043  
1044        return ret;
1045      }
1046  
1047  
1048  
1049      /**
1050       * Trigger the relevant event handler
1051       * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
1052       * @param {object} event the original event object
1053       * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
1054       * @param {string} gesture the gesture to trigger a handler for : PINCH or SWIPE {@link $.fn.swipe.gestures}
1055       * @return Boolean False, to indicate that the event should stop propagation, or void.
1056       * @inner
1057       */
1058      function triggerHandlerForGesture(event, phase, gesture) {
1059  
1060        var ret;
1061  
1062        //SWIPES....
1063        if (gesture == SWIPE) {
1064          //Trigger status every time..
1065          $element.trigger('swipeStatus', [phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData, currentDirection]);
1066  
1067          if (options.swipeStatus) {
1068            ret = options.swipeStatus.call($element, event, phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData, currentDirection);
1069            //If the status cancels, then dont run the subsequent event handlers..
1070            if (ret === false) return false;
1071          }
1072  
1073          if (phase == PHASE_END && validateSwipe()) {
1074  
1075            //Cancel any taps that were in progress...
1076            clearTimeout(singleTapTimeout);
1077            clearTimeout(holdTimeout);
1078  
1079            $element.trigger('swipe', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
1080  
1081            if (options.swipe) {
1082              ret = options.swipe.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1083              //If the status cancels, then dont run the subsequent event handlers..
1084              if (ret === false) return false;
1085            }
1086  
1087            //trigger direction specific event handlers
1088            switch (direction) {
1089              case LEFT:
1090                $element.trigger('swipeLeft', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
1091  
1092                if (options.swipeLeft) {
1093                  ret = options.swipeLeft.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1094                }
1095                break;
1096  
1097              case RIGHT:
1098                $element.trigger('swipeRight', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
1099  
1100                if (options.swipeRight) {
1101                  ret = options.swipeRight.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1102                }
1103                break;
1104  
1105              case UP:
1106                $element.trigger('swipeUp', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
1107  
1108                if (options.swipeUp) {
1109                  ret = options.swipeUp.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1110                }
1111                break;
1112  
1113              case DOWN:
1114                $element.trigger('swipeDown', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
1115  
1116                if (options.swipeDown) {
1117                  ret = options.swipeDown.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1118                }
1119                break;
1120            }
1121          }
1122        }
1123  
1124  
1125        //PINCHES....
1126        if (gesture == PINCH) {
1127          $element.trigger('pinchStatus', [phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1128  
1129          if (options.pinchStatus) {
1130            ret = options.pinchStatus.call($element, event, phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1131            //If the status cancels, then dont run the subsequent event handlers..
1132            if (ret === false) return false;
1133          }
1134  
1135          if (phase == PHASE_END && validatePinch()) {
1136  
1137            switch (pinchDirection) {
1138              case IN:
1139                $element.trigger('pinchIn', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1140  
1141                if (options.pinchIn) {
1142                  ret = options.pinchIn.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1143                }
1144                break;
1145  
1146              case OUT:
1147                $element.trigger('pinchOut', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1148  
1149                if (options.pinchOut) {
1150                  ret = options.pinchOut.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1151                }
1152                break;
1153            }
1154          }
1155        }
1156  
1157        if (gesture == TAP) {
1158          if (phase === PHASE_CANCEL || phase === PHASE_END) {
1159  
1160            clearTimeout(singleTapTimeout);
1161            clearTimeout(holdTimeout);
1162  
1163            //If we are also looking for doubelTaps, wait incase this is one...
1164            if (hasDoubleTap() && !inDoubleTap()) {
1165              doubleTapStartTime = getTimeStamp();
1166  
1167              //Now wait for the double tap timeout, and trigger this single tap
1168              //if its not cancelled by a double tap
1169              singleTapTimeout = setTimeout($.proxy(function() {
1170                doubleTapStartTime = null;
1171                $element.trigger('tap', [event.target]);
1172  
1173                if (options.tap) {
1174                  ret = options.tap.call($element, event, event.target);
1175                }
1176              }, this), options.doubleTapThreshold);
1177  
1178            } else {
1179              doubleTapStartTime = null;
1180              $element.trigger('tap', [event.target]);
1181              if (options.tap) {
1182                ret = options.tap.call($element, event, event.target);
1183              }
1184            }
1185          }
1186        } else if (gesture == DOUBLE_TAP) {
1187          if (phase === PHASE_CANCEL || phase === PHASE_END) {
1188            clearTimeout(singleTapTimeout);
1189            clearTimeout(holdTimeout);
1190            doubleTapStartTime = null;
1191            $element.trigger('doubletap', [event.target]);
1192  
1193            if (options.doubleTap) {
1194              ret = options.doubleTap.call($element, event, event.target);
1195            }
1196          }
1197        } else if (gesture == LONG_TAP) {
1198          if (phase === PHASE_CANCEL || phase === PHASE_END) {
1199            clearTimeout(singleTapTimeout);
1200            doubleTapStartTime = null;
1201  
1202            $element.trigger('longtap', [event.target]);
1203            if (options.longTap) {
1204              ret = options.longTap.call($element, event, event.target);
1205            }
1206          }
1207        }
1208  
1209        return ret;
1210      }
1211  
1212  
1213      //
1214      // GESTURE VALIDATION
1215      //
1216  
1217      /**
1218       * Checks the user has swipe far enough
1219       * @return Boolean if <code>threshold</code> has been set, return true if the threshold was met, else false.
1220       * If no threshold was set, then we return true.
1221       * @inner
1222       */
1223      function validateSwipeDistance() {
1224        var valid = true;
1225        //If we made it past the min swipe distance..
1226        if (options.threshold !== null) {
1227          valid = distance >= options.threshold;
1228        }
1229  
1230        return valid;
1231      }
1232  
1233      /**
1234       * Checks the user has swiped back to cancel.
1235       * @return Boolean if <code>cancelThreshold</code> has been set, return true if the cancelThreshold was met, else false.
1236       * If no cancelThreshold was set, then we return true.
1237       * @inner
1238       */
1239      function didSwipeBackToCancel() {
1240        var cancelled = false;
1241        if (options.cancelThreshold !== null && direction !== null) {
1242          cancelled = (getMaxDistance(direction) - distance) >= options.cancelThreshold;
1243        }
1244  
1245        return cancelled;
1246      }
1247  
1248      /**
1249       * Checks the user has pinched far enough
1250       * @return Boolean if <code>pinchThreshold</code> has been set, return true if the threshold was met, else false.
1251       * If no threshold was set, then we return true.
1252       * @inner
1253       */
1254      function validatePinchDistance() {
1255        if (options.pinchThreshold !== null) {
1256          return pinchDistance >= options.pinchThreshold;
1257        }
1258        return true;
1259      }
1260  
1261      /**
1262       * Checks that the time taken to swipe meets the minimum / maximum requirements
1263       * @return Boolean
1264       * @inner
1265       */
1266      function validateSwipeTime() {
1267        var result;
1268        //If no time set, then return true
1269        if (options.maxTimeThreshold) {
1270          if (duration >= options.maxTimeThreshold) {
1271            result = false;
1272          } else {
1273            result = true;
1274          }
1275        } else {
1276          result = true;
1277        }
1278  
1279        return result;
1280      }
1281  
1282  
1283      /**
1284       * Checks direction of the swipe and the value allowPageScroll to see if we should allow or prevent the default behaviour from occurring.
1285       * This will essentially allow page scrolling or not when the user is swiping on a touchSwipe object.
1286       * @param {object} jqEvent The normalised jQuery representation of the event object.
1287       * @param {string} direction The direction of the event. See {@link $.fn.swipe.directions}
1288       * @see $.fn.swipe.directions
1289       * @inner
1290       */
1291      function validateDefaultEvent(jqEvent, direction) {
1292  
1293        //If the option is set, allways allow the event to bubble up (let user handle weirdness)
1294        if (options.preventDefaultEvents === false) {
1295          return;
1296        }
1297  
1298        if (options.allowPageScroll === NONE) {
1299          jqEvent.preventDefault();
1300        } else {
1301          var auto = options.allowPageScroll === AUTO;
1302  
1303          switch (direction) {
1304            case LEFT:
1305              if ((options.swipeLeft && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1306                jqEvent.preventDefault();
1307              }
1308              break;
1309  
1310            case RIGHT:
1311              if ((options.swipeRight && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1312                jqEvent.preventDefault();
1313              }
1314              break;
1315  
1316            case UP:
1317              if ((options.swipeUp && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1318                jqEvent.preventDefault();
1319              }
1320              break;
1321  
1322            case DOWN:
1323              if ((options.swipeDown && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1324                jqEvent.preventDefault();
1325              }
1326              break;
1327  
1328            case NONE:
1329  
1330              break;
1331          }
1332        }
1333      }
1334  
1335  
1336      // PINCHES
1337      /**
1338       * Returns true of the current pinch meets the thresholds
1339       * @return Boolean
1340       * @inner
1341       */
1342      function validatePinch() {
1343        var hasCorrectFingerCount = validateFingers();
1344        var hasEndPoint = validateEndPoint();
1345        var hasCorrectDistance = validatePinchDistance();
1346        return hasCorrectFingerCount && hasEndPoint && hasCorrectDistance;
1347  
1348      }
1349  
1350      /**
1351       * Returns true if any Pinch events have been registered
1352       * @return Boolean
1353       * @inner
1354       */
1355      function hasPinches() {
1356        //Enure we dont return 0 or null for false values
1357        return !!(options.pinchStatus || options.pinchIn || options.pinchOut);
1358      }
1359  
1360      /**
1361       * Returns true if we are detecting pinches, and have one
1362       * @return Boolean
1363       * @inner
1364       */
1365      function didPinch() {
1366        //Enure we dont return 0 or null for false values
1367        return !!(validatePinch() && hasPinches());
1368      }
1369  
1370  
1371  
1372  
1373      // SWIPES
1374      /**
1375       * Returns true if the current swipe meets the thresholds
1376       * @return Boolean
1377       * @inner
1378       */
1379      function validateSwipe() {
1380        //Check validity of swipe
1381        var hasValidTime = validateSwipeTime();
1382        var hasValidDistance = validateSwipeDistance();
1383        var hasCorrectFingerCount = validateFingers();
1384        var hasEndPoint = validateEndPoint();
1385        var didCancel = didSwipeBackToCancel();
1386  
1387        // if the user swiped more than the minimum length, perform the appropriate action
1388        // hasValidDistance is null when no distance is set
1389        var valid = !didCancel && hasEndPoint && hasCorrectFingerCount && hasValidDistance && hasValidTime;
1390  
1391        return valid;
1392      }
1393  
1394      /**
1395       * Returns true if any Swipe events have been registered
1396       * @return Boolean
1397       * @inner
1398       */
1399      function hasSwipes() {
1400        //Enure we dont return 0 or null for false values
1401        return !!(options.swipe || options.swipeStatus || options.swipeLeft || options.swipeRight || options.swipeUp || options.swipeDown);
1402      }
1403  
1404  
1405      /**
1406       * Returns true if we are detecting swipes and have one
1407       * @return Boolean
1408       * @inner
1409       */
1410      function didSwipe() {
1411        //Enure we dont return 0 or null for false values
1412        return !!(validateSwipe() && hasSwipes());
1413      }
1414  
1415      /**
1416       * Returns true if we have matched the number of fingers we are looking for
1417       * @return Boolean
1418       * @inner
1419       */
1420      function validateFingers() {
1421        //The number of fingers we want were matched, or on desktop we ignore
1422        return ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH);
1423      }
1424  
1425      /**
1426       * Returns true if we have an end point for the swipe
1427       * @return Boolean
1428       * @inner
1429       */
1430      function validateEndPoint() {
1431        //We have an end value for the finger
1432        return fingerData[0].end.x !== 0;
1433      }
1434  
1435      // TAP / CLICK
1436      /**
1437       * Returns true if a click / tap events have been registered
1438       * @return Boolean
1439       * @inner
1440       */
1441      function hasTap() {
1442        //Enure we dont return 0 or null for false values
1443        return !!(options.tap);
1444      }
1445  
1446      /**
1447       * Returns true if a double tap events have been registered
1448       * @return Boolean
1449       * @inner
1450       */
1451      function hasDoubleTap() {
1452        //Enure we dont return 0 or null for false values
1453        return !!(options.doubleTap);
1454      }
1455  
1456      /**
1457       * Returns true if any long tap events have been registered
1458       * @return Boolean
1459       * @inner
1460       */
1461      function hasLongTap() {
1462        //Enure we dont return 0 or null for false values
1463        return !!(options.longTap);
1464      }
1465  
1466      /**
1467       * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1468       * @return Boolean
1469       * @inner
1470       */
1471      function validateDoubleTap() {
1472        if (doubleTapStartTime == null) {
1473          return false;
1474        }
1475        var now = getTimeStamp();
1476        return (hasDoubleTap() && ((now - doubleTapStartTime) <= options.doubleTapThreshold));
1477      }
1478  
1479      /**
1480       * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1481       * @return Boolean
1482       * @inner
1483       */
1484      function inDoubleTap() {
1485        return validateDoubleTap();
1486      }
1487  
1488  
1489      /**
1490       * Returns true if we have a valid tap
1491       * @return Boolean
1492       * @inner
1493       */
1494      function validateTap() {
1495        return ((fingerCount === 1 || !SUPPORTS_TOUCH) && (isNaN(distance) || distance < options.threshold));
1496      }
1497  
1498      /**
1499       * Returns true if we have a valid long tap
1500       * @return Boolean
1501       * @inner
1502       */
1503      function validateLongTap() {
1504        //slight threshold on moving finger
1505        return ((duration > options.longTapThreshold) && (distance < DOUBLE_TAP_THRESHOLD));
1506      }
1507  
1508      /**
1509       * Returns true if we are detecting taps and have one
1510       * @return Boolean
1511       * @inner
1512       */
1513      function didTap() {
1514        //Enure we dont return 0 or null for false values
1515        return !!(validateTap() && hasTap());
1516      }
1517  
1518  
1519      /**
1520       * Returns true if we are detecting double taps and have one
1521       * @return Boolean
1522       * @inner
1523       */
1524      function didDoubleTap() {
1525        //Enure we dont return 0 or null for false values
1526        return !!(validateDoubleTap() && hasDoubleTap());
1527      }
1528  
1529      /**
1530       * Returns true if we are detecting long taps and have one
1531       * @return Boolean
1532       * @inner
1533       */
1534      function didLongTap() {
1535        //Enure we dont return 0 or null for false values
1536        return !!(validateLongTap() && hasLongTap());
1537      }
1538  
1539  
1540  
1541  
1542      // MULTI FINGER TOUCH
1543      /**
1544       * Starts tracking the time between 2 finger releases, and keeps track of how many fingers we initially had up
1545       * @inner
1546       */
1547      function startMultiFingerRelease(event) {
1548        previousTouchEndTime = getTimeStamp();
1549        fingerCountAtRelease = event.touches.length + 1;
1550      }
1551  
1552      /**
1553       * Cancels the tracking of time between 2 finger releases, and resets counters
1554       * @inner
1555       */
1556      function cancelMultiFingerRelease() {
1557        previousTouchEndTime = 0;
1558        fingerCountAtRelease = 0;
1559      }
1560  
1561      /**
1562       * Checks if we are in the threshold between 2 fingers being released
1563       * @return Boolean
1564       * @inner
1565       */
1566      function inMultiFingerRelease() {
1567  
1568        var withinThreshold = false;
1569  
1570        if (previousTouchEndTime) {
1571          var diff = getTimeStamp() - previousTouchEndTime
1572          if (diff <= options.fingerReleaseThreshold) {
1573            withinThreshold = true;
1574          }
1575        }
1576  
1577        return withinThreshold;
1578      }
1579  
1580  
1581      /**
1582       * gets a data flag to indicate that a touch is in progress
1583       * @return Boolean
1584       * @inner
1585       */
1586      function getTouchInProgress() {
1587        //strict equality to ensure only true and false are returned
1588        return !!($element.data(PLUGIN_NS + '_intouch') === true);
1589      }
1590  
1591      /**
1592       * Sets a data flag to indicate that a touch is in progress
1593       * @param {boolean} val The value to set the property to
1594       * @inner
1595       */
1596      function setTouchInProgress(val) {
1597  
1598        //If destroy is called in an event handler, we have no el, and we have already cleaned up, so return.
1599        if(!$element) { return; }
1600  
1601        //Add or remove event listeners depending on touch status
1602        if (val === true) {
1603          $element.on(MOVE_EV, touchMove);
1604          $element.on(END_EV, touchEnd);
1605  
1606          //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1607          if (LEAVE_EV) {
1608            $element.on(LEAVE_EV, touchLeave);
1609          }
1610        } else {
1611  
1612          $element.off(MOVE_EV, touchMove, false);
1613          $element.off(END_EV, touchEnd, false);
1614  
1615          //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1616          if (LEAVE_EV) {
1617            $element.off(LEAVE_EV, touchLeave, false);
1618          }
1619        }
1620  
1621  
1622        //strict equality to ensure only true and false can update the value
1623        $element.data(PLUGIN_NS + '_intouch', val === true);
1624      }
1625  
1626  
1627      /**
1628       * Creates the finger data for the touch/finger in the event object.
1629       * @param {int} id The id to store the finger data under (usually the order the fingers were pressed)
1630       * @param {object} evt The event object containing finger data
1631       * @return finger data object
1632       * @inner
1633       */
1634      function createFingerData(id, evt) {
1635        var f = {
1636          start: {
1637            x: 0,
1638            y: 0
1639          },
1640          last: {
1641            x: 0,
1642            y: 0
1643          },
1644          end: {
1645            x: 0,
1646            y: 0
1647          }
1648        };
1649        f.start.x = f.last.x = f.end.x = evt.pageX || evt.clientX;
1650        f.start.y = f.last.y = f.end.y = evt.pageY || evt.clientY;
1651        fingerData[id] = f;
1652        return f;
1653      }
1654  
1655      /**
1656       * Updates the finger data for a particular event object
1657       * @param {object} evt The event object containing the touch/finger data to upadte
1658       * @return a finger data object.
1659       * @inner
1660       */
1661      function updateFingerData(evt) {
1662        var id = evt.identifier !== undefined ? evt.identifier : 0;
1663        var f = getFingerData(id);
1664  
1665        if (f === null) {
1666          f = createFingerData(id, evt);
1667        }
1668  
1669        f.last.x = f.end.x;
1670        f.last.y = f.end.y;
1671  
1672        f.end.x = evt.pageX || evt.clientX;
1673        f.end.y = evt.pageY || evt.clientY;
1674  
1675        return f;
1676      }
1677  
1678      /**
1679       * Returns a finger data object by its event ID.
1680       * Each touch event has an identifier property, which is used
1681       * to track repeat touches
1682       * @param {int} id The unique id of the finger in the sequence of touch events.
1683       * @return a finger data object.
1684       * @inner
1685       */
1686      function getFingerData(id) {
1687        return fingerData[id] || null;
1688      }
1689  
1690  
1691      /**
1692       * Sets the maximum distance swiped in the given direction.
1693       * If the new value is lower than the current value, the max value is not changed.
1694       * @param {string}  direction The direction of the swipe
1695       * @param {int}  distance The distance of the swipe
1696       * @inner
1697       */
1698      function setMaxDistance(direction, distance) {
1699        if(direction==NONE) return;
1700        distance = Math.max(distance, getMaxDistance(direction));
1701        maximumsMap[direction].distance = distance;
1702      }
1703  
1704      /**
1705       * gets the maximum distance swiped in the given direction.
1706       * @param {string}  direction The direction of the swipe
1707       * @return int  The distance of the swipe
1708       * @inner
1709       */
1710      function getMaxDistance(direction) {
1711        if (maximumsMap[direction]) return maximumsMap[direction].distance;
1712        return undefined;
1713      }
1714  
1715      /**
1716       * Creats a map of directions to maximum swiped values.
1717       * @return Object A dictionary of maximum values, indexed by direction.
1718       * @inner
1719       */
1720      function createMaximumsData() {
1721        var maxData = {};
1722        maxData[LEFT] = createMaximumVO(LEFT);
1723        maxData[RIGHT] = createMaximumVO(RIGHT);
1724        maxData[UP] = createMaximumVO(UP);
1725        maxData[DOWN] = createMaximumVO(DOWN);
1726  
1727        return maxData;
1728      }
1729  
1730      /**
1731       * Creates a map maximum swiped values for a given swipe direction
1732       * @param {string} The direction that these values will be associated with
1733       * @return Object Maximum values
1734       * @inner
1735       */
1736      function createMaximumVO(dir) {
1737        return {
1738          direction: dir,
1739          distance: 0
1740        }
1741      }
1742  
1743  
1744      //
1745      // MATHS / UTILS
1746      //
1747  
1748      /**
1749       * Calculate the duration of the swipe
1750       * @return int
1751       * @inner
1752       */
1753      function calculateDuration() {
1754        return endTime - startTime;
1755      }
1756  
1757      /**
1758       * Calculate the distance between 2 touches (pinch)
1759       * @param {point} startPoint A point object containing x and y co-ordinates
1760       * @param {point} endPoint A point object containing x and y co-ordinates
1761       * @return int;
1762       * @inner
1763       */
1764      function calculateTouchesDistance(startPoint, endPoint) {
1765        var diffX = Math.abs(startPoint.x - endPoint.x);
1766        var diffY = Math.abs(startPoint.y - endPoint.y);
1767  
1768        return Math.round(Math.sqrt(diffX * diffX + diffY * diffY));
1769      }
1770  
1771      /**
1772       * Calculate the zoom factor between the start and end distances
1773       * @param {int} startDistance Distance (between 2 fingers) the user started pinching at
1774       * @param {int} endDistance Distance (between 2 fingers) the user ended pinching at
1775       * @return float The zoom value from 0 to 1.
1776       * @inner
1777       */
1778      function calculatePinchZoom(startDistance, endDistance) {
1779        var percent = (endDistance / startDistance) * 1;
1780        return percent.toFixed(2);
1781      }
1782  
1783  
1784      /**
1785       * Returns the pinch direction, either IN or OUT for the given points
1786       * @return string Either {@link $.fn.swipe.directions.IN} or {@link $.fn.swipe.directions.OUT}
1787       * @see $.fn.swipe.directions
1788       * @inner
1789       */
1790      function calculatePinchDirection() {
1791        if (pinchZoom < 1) {
1792          return OUT;
1793        } else {
1794          return IN;
1795        }
1796      }
1797  
1798  
1799      /**
1800       * Calculate the length / distance of the swipe
1801       * @param {point} startPoint A point object containing x and y co-ordinates
1802       * @param {point} endPoint A point object containing x and y co-ordinates
1803       * @return int
1804       * @inner
1805       */
1806      function calculateDistance(startPoint, endPoint) {
1807        return Math.round(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)));
1808      }
1809  
1810      /**
1811       * Calculate the angle of the swipe
1812       * @param {point} startPoint A point object containing x and y co-ordinates
1813       * @param {point} endPoint A point object containing x and y co-ordinates
1814       * @return int
1815       * @inner
1816       */
1817      function calculateAngle(startPoint, endPoint) {
1818        var x = startPoint.x - endPoint.x;
1819        var y = endPoint.y - startPoint.y;
1820        var r = Math.atan2(y, x); //radians
1821        var angle = Math.round(r * 180 / Math.PI); //degrees
1822  
1823        //ensure value is positive
1824        if (angle < 0) {
1825          angle = 360 - Math.abs(angle);
1826        }
1827  
1828        return angle;
1829      }
1830  
1831      /**
1832       * Calculate the direction of the swipe
1833       * This will also call calculateAngle to get the latest angle of swipe
1834       * @param {point} startPoint A point object containing x and y co-ordinates
1835       * @param {point} endPoint A point object containing x and y co-ordinates
1836       * @return string Either {@link $.fn.swipe.directions.LEFT} / {@link $.fn.swipe.directions.RIGHT} / {@link $.fn.swipe.directions.DOWN} / {@link $.fn.swipe.directions.UP}
1837       * @see $.fn.swipe.directions
1838       * @inner
1839       */
1840      function calculateDirection(startPoint, endPoint) {
1841  
1842        if( comparePoints(startPoint, endPoint) ) {
1843          return NONE;
1844        }
1845  
1846        var angle = calculateAngle(startPoint, endPoint);
1847  
1848        if ((angle <= 45) && (angle >= 0)) {
1849          return LEFT;
1850        } else if ((angle <= 360) && (angle >= 315)) {
1851          return LEFT;
1852        } else if ((angle >= 135) && (angle <= 225)) {
1853          return RIGHT;
1854        } else if ((angle > 45) && (angle < 135)) {
1855          return DOWN;
1856        } else {
1857          return UP;
1858        }
1859      }
1860  
1861  
1862      /**
1863       * Returns a MS time stamp of the current time
1864       * @return int
1865       * @inner
1866       */
1867      function getTimeStamp() {
1868        var now = new Date();
1869        return now.getTime();
1870      }
1871  
1872  
1873  
1874      /**
1875       * Returns a bounds object with left, right, top and bottom properties for the element specified.
1876       * @param {DomNode} The DOM node to get the bounds for.
1877       */
1878      function getbounds(el) {
1879        el = $(el);
1880        var offset = el.offset();
1881  
1882        var bounds = {
1883          left: offset.left,
1884          right: offset.left + el.outerWidth(),
1885          top: offset.top,
1886          bottom: offset.top + el.outerHeight()
1887        }
1888  
1889        return bounds;
1890      }
1891  
1892  
1893      /**
1894       * Checks if the point object is in the bounds object.
1895       * @param {object} point A point object.
1896       * @param {int} point.x The x value of the point.
1897       * @param {int} point.y The x value of the point.
1898       * @param {object} bounds The bounds object to test
1899       * @param {int} bounds.left The leftmost value
1900       * @param {int} bounds.right The righttmost value
1901       * @param {int} bounds.top The topmost value
1902       * @param {int} bounds.bottom The bottommost value
1903       */
1904      function isInBounds(point, bounds) {
1905        return (point.x > bounds.left && point.x < bounds.right && point.y > bounds.top && point.y < bounds.bottom);
1906      };
1907  
1908      /**
1909       * Checks if the two points are equal
1910       * @param {object} point A point object.
1911       * @param {object} point B point object.
1912       * @return true of the points match
1913       */
1914      function comparePoints(pointA, pointB) {
1915        return (pointA.x == pointB.x && pointA.y == pointB.y);
1916      }
1917  
1918  
1919    }
1920  
1921  
1922  
1923  
1924    /**
1925     * A catch all handler that is triggered for all swipe directions.
1926     * @name $.fn.swipe#swipe
1927     * @event
1928     * @default null
1929     * @param {EventObject} event The original event object
1930     * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1931     * @param {int} distance The distance the user swiped
1932     * @param {int} duration The duration of the swipe in milliseconds
1933     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1934     * @param {object} fingerData The coordinates of fingers in event
1935     * @param {string} currentDirection The current direction the user is swiping.
1936     */
1937  
1938  
1939  
1940  
1941    /**
1942     * A handler that is triggered for "left" swipes.
1943     * @name $.fn.swipe#swipeLeft
1944     * @event
1945     * @default null
1946     * @param {EventObject} event The original event object
1947     * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1948     * @param {int} distance The distance the user swiped
1949     * @param {int} duration The duration of the swipe in milliseconds
1950     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1951     * @param {object} fingerData The coordinates of fingers in event
1952     * @param {string} currentDirection The current direction the user is swiping.
1953     */
1954  
1955    /**
1956     * A handler that is triggered for "right" swipes.
1957     * @name $.fn.swipe#swipeRight
1958     * @event
1959     * @default null
1960     * @param {EventObject} event The original event object
1961     * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1962     * @param {int} distance The distance the user swiped
1963     * @param {int} duration The duration of the swipe in milliseconds
1964     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1965     * @param {object} fingerData The coordinates of fingers in event
1966     * @param {string} currentDirection The current direction the user is swiping.
1967     */
1968  
1969    /**
1970     * A handler that is triggered for "up" swipes.
1971     * @name $.fn.swipe#swipeUp
1972     * @event
1973     * @default null
1974     * @param {EventObject} event The original event object
1975     * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1976     * @param {int} distance The distance the user swiped
1977     * @param {int} duration The duration of the swipe in milliseconds
1978     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1979     * @param {object} fingerData The coordinates of fingers in event
1980     * @param {string} currentDirection The current direction the user is swiping.
1981     */
1982  
1983    /**
1984     * A handler that is triggered for "down" swipes.
1985     * @name $.fn.swipe#swipeDown
1986     * @event
1987     * @default null
1988     * @param {EventObject} event The original event object
1989     * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1990     * @param {int} distance The distance the user swiped
1991     * @param {int} duration The duration of the swipe in milliseconds
1992     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1993     * @param {object} fingerData The coordinates of fingers in event
1994     * @param {string} currentDirection The current direction the user is swiping.
1995     */
1996  
1997    /**
1998     * A handler triggered for every phase of the swipe. This handler is constantly f
1998ired for the duration of the pinch.
1999     * This is triggered regardless of swipe thresholds.
2000     * @name $.fn.swipe#swipeStatus
2001     * @event
2002     * @default null
2003     * @param {EventObject} event The original event object
2004     * @param {string} phase The phase of the swipe event. See {@link $.fn.swipe.phases}
2005     * @param {string} direction The direction the user swiped in. This is null if the user has yet to move. See {@link $.fn.swipe.directions}
2006     * @param {int} distance The distance the user swiped. This is 0 if the user has yet to move.
2007     * @param {int} duration The duration of the swipe in milliseconds
2008     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2009     * @param {object} fingerData The coordinates of fingers in event
2010     * @param {string} currentDirection The current direction the user is swiping.
2011     */
2012  
2013    /**
2014     * A handler triggered for pinch in events.
2015     * @name $.fn.swipe#pinchIn
2016     * @event
2017     * @default null
2018     * @param {EventObject} event The original event object
2019     * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
2020     * @param {int} distance The distance the user pinched
2021     * @param {int} duration The duration of the swipe in milliseconds
2022     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2023     * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
2024     * @param {object} fingerData The coordinates of fingers in event
2025     */
2026  
2027    /**
2028     * A handler triggered for pinch out events.
2029     * @name $.fn.swipe#pinchOut
2030     * @event
2031     * @default null
2032     * @param {EventObject} event The original event object
2033     * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
2034     * @param {int} distance The distance the user pinched
2035     * @param {int} duration The duration of the swipe in milliseconds
2036     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2037     * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
2038     * @param {object} fingerData The coordinates of fingers in event
2039     */
2040  
2041    /**
2042     * A handler triggered for all pinch events. This handler is constantly fired for the duration of the pinch. This is triggered regardless of thresholds.
2043     * @name $.fn.swipe#pinchStatus
2044     * @event
2045     * @default null
2046     * @param {EventObject} event The original event object
2047     * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
2048     * @param {int} distance The distance the user pinched
2049     * @param {int} duration The duration of the swipe in milliseconds
2050     * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2051     * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
2052     * @param {object} fingerData The coordinates of fingers in event
2053     */
2054  
2055    /**
2056     * A click handler triggered when a user simply clicks, rather than swipes on an element.
2057     * This is deprecated since version 1.6.2, any assignment to click will be assigned to the tap handler.
2058     * You cannot use <code>on</code> to bind to this event as the default jQ <code>click</code> event will be triggered.
2059     * Use the <code>tap</code> event instead.
2060     * @name $.fn.swipe#click
2061     * @event
2062     * @deprecated since version 1.6.2, please use {@link $.fn.swipe#tap} instead
2063     * @default null
2064     * @param {EventObject} event The original event object
2065     * @param {DomObject} target The element clicked on.
2066     */
2067  
2068    /**
2069     * A click / tap handler triggered when a user simply clicks or taps, rather than swipes on an element.
2070     * @name $.fn.swipe#tap
2071     * @event
2072     * @default null
2073     * @param {EventObject} event The original event object
2074     * @param {DomObject} target The element clicked on.
2075     */
2076  
2077    /**
2078     * A double tap handler triggered when a user double clicks or taps on an element.
2079     * You can set the time delay for a double tap with the {@link $.fn.swipe.defaults#doubleTapThreshold} property.
2080     * Note: If you set both <code>doubleTap</code> and <code>tap</code> handlers, the <code>tap</code> event will be delayed by the <code>doubleTapThreshold</code>
2081     * as the script needs to check if its a double tap.
2082     * @name $.fn.swipe#doubleTap
2083     * @see  $.fn.swipe.defaults#doubleTapThreshold
2084     * @event
2085     * @default null
2086     * @param {EventObject} event The original event object
2087     * @param {DomObject} target The element clicked on.
2088     */
2089  
2090    /**
2091     * A long tap handler triggered once a tap has been release if the tap was longer than the longTapThreshold.
2092     * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2093     * @name $.fn.swipe#longTap
2094     * @see  $.fn.swipe.defaults#longTapThreshold
2095     * @event
2096     * @default null
2097     * @param {EventObject} event The original event object
2098     * @param {DomObject} target The element clicked on.
2099     */
2100  
2101    /**
2102     * A hold tap handler triggered as soon as the longTapThreshold is reached
2103     * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2104     * @name $.fn.swipe#hold
2105     * @see  $.fn.swipe.defaults#longTapThreshold
2106     * @event
2107     * @default null
2108     * @param {EventObject} event The original event object
2109     * @param {DomObject} target The element clicked on.
2110     */
2111  
2112  }));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.