Best Python code snippet using fMBT_python
jquery.gestures.js
Source:jquery.gestures.js
1(function(jQuery, $, window){2 /*jslint undef: true, browser: true, continue: true, eqeq: true, vars: true, forin: true, white: true, newcap: false, nomen: true, plusplus: true, maxerr: 50, indent: 4 */3/**4 * jGestures: a jQuery plugin for gesture events5 * Copyright 2010-2011 Neue Digitale / Razorfish GmbH6 * Copyright 2011-2012, Razorfish GmbH7 *8 * Licensed under the Apache License, Version 2.0 (the "License");9 * you may not use this file except in compliance with the License.10 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.011 * Unless required by applicable law or agreed to in writing, software12 * distributed under the License is distributed on an "AS IS" BASIS,13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14 * See the License for the specific language governing permissions and15 * limitations under the License.16 *17 * @fileOverview18 * Razorfish GmbH javascript library: add touch events such as 'pinch',19 * 'rotate', 'swipe', 'tap' and 'orientationchange' on capable user agents.20 * For incapable devices there's a basic event substitution: a "tapone" event21 * can be triggered by "clicking", a "swipeone" by performing a swipe-ish22 * gesture using the mouse (buttondown - mousemove - buttonup).23 *24 * This is still a beta version, bugfixes and improvements appreciated.25 *26 * @author martin.krause@razorfish.de27 * @version 0.90-shake28 *29 * @requires30 * jQuery JavaScript Library v1.4.2 - http://jquery.com/31 * Copyright 2010, John Resig32 * Dual licensed under the MIT or GPL Version 2 licenses.33 * http://jquery.org/license34 *35 * @example jQuery('#swipe').bind('swipeone',eventHandler);36 *37 * Notification on native events:38 * On every native touchstart, touchend, gesturestart and gestureend-event,39 * jgestures triggers a corresponding custom event40 * ('jGestures.touchstart', 'jGestures.touchend;start', 'jGestures.touchend;processed',41 * 'jGestures.gesturestart', 'jGestures.gestureend;start', 'jGestures.gestureend;processed') on the event-element.42 * The eventhandler's second argument represents the original touch event (yes: including all touchpoints).43 * Use this if you need very detailed control e.g. kinetic scrolling or implementing additional gestures.44 *45 * Every jGesture-eventhandler receives a custom object as second argument46 * containing the original event (originalEvent property) and processed47 * information (such as delta values and timesptamp).48 * Example:{49 * type: eventtype e.g. "swipe","pinch",50 * originalEvent: {DOM-Event},51 * // default: just one entry on the delta-array - the first touchpoint52 * // the first touchpoint is the reference point for every gesture,53 * // because moving touchpoints in various directions would result in54 * // a gesture.55 * // delta and direction details are just provided for touch not for gesture / motion events56 * delta : [57 * {58 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)59 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)60 * moved: {Number}, // distance: relative to the original touchpoint61 * startX: {Number} , // relative to the original touchpoint62 * startY: {Number} ,// relative to the original touchpoint63 * } ],64 * // based on the first touchpoint65 * direction : { // relative to the last touchevent (e.g. touchmove!)66 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)67 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)68 * lastX : {Number}, // -1,0,+1 || null (orientationchange) // relative to the last touchevent (e.g. touchmove!)69 * lastY : {Number}, // -1,0,+1 || null (orientationchange)// relative to the last touchevent (e.g. touchmove!)70 * startX: {Number} , // relative to the original touchpoint71 * startY: {Number} ,// relative to the original touchpoint72 * },73 * rotation: {Number} || null, // gestureonly: amount of rotation relative to the current position NOT the original74 * scale: {Number} || null, // gestureonly: amount of scaling relative to the current position NOT the original75 * duration: {Number}, // ms: relative to the original touchpoint76 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint77 * };78 *79 * Available jGesture-events can be grouped into:80 *81 *82 * Device events:83 * The jGesture-Events in this group are triggered by the device.84 *85 * @event 'orientationchange'86 * The device is turned clockwise or counterclockwise. This event is triggered87 * by the device and might use an internal gyroscope.88 * obj.description:89 * orientationchange:landscape:clockwise:-9090 * orientationchange:portrait:default:091 * orientationchange:landscape:counterclockwise|portrait:9092 * orientationchange:portrait:upsidedown:18093 *94 *95 * Move events:96 * The jGesture-Events in this group are triggered during the touch/gesture97 * execution whenever a touchpoint changes.98 * In contrast to touchend/gestureend-events which are triggered after99 * the touch/gesture has completed.100 *101 * @event 'pinch'102 * Is triggered during a pinch gesture (two fingers moving away from or103 * towards each other).104 * obj.description:105 * pinch:-1:close106 * pinch:+1:open107 *108 * @event 'rotate'109 * Is triggered during a rotation gesture (two fingers rotating clockwise110 * or counterclockwise).111 * obj.description:112 * rotate:-1:counterclockwise113 * rotate:+1:+clockwise114 *115 * @event 'swipemove'116 * Is triggered during a swipe move gesture (finger(s) being moved around117 * the device, e.g. dragging)118 * obj.description:119 * swipemove:1:left:down120 * swipemove:1:left:up121 * swipemove:1:left:steady122 * swipemove:1:right:down123 * swipemove:1:right:up124 * swipemove:1:right:steady125 * swipemove:2:left:down126 * swipemove:2:left:up127 * swipemove:2:left:steady128 * swipemove:2:right:down129 * swipemove:2:right:up130 * swipemove:2:right:steady131 * swipemove:2:left:down132 * swipemove:3:left:up133 * swipemove:3:left:steady134 * swipemove:3:right:down135 * swipemove:3:right:up136 * swipemove:3:right:steady137 * swipemove:3:left:down138 * swipemove:4:left:up139 * swipemove:4:left:steady140 * swipemove:4:right:down141 * swipemove:4:right:up142 * swipemove:4:right:steady143 *144 *145 * Toucheend events:146 * The jGesture-Events in this group are triggered after the touch/gesture147 * has completed.148 * In contrast to touchmove-events which are triggered during the touch/gesture149 * execution whenever a touchpoint changes.150 *151 * @event 'swipeone'152 * Is triggered after a swipe move gesture with one touchpoint (one finger153 * was moved around the device)154 * obj.description:155 * swipeone:1:left:down156 * swipeone:1:left:up157 * swipeone:1:left:steady158 * swipeone:1:right:down159 * swipeone:1:right:up160 * swipeone:1:right:steady161 *162 * @event 'swipetwo'163 * Is triggered after a swipe move gesture with two touchpoints (two fingers164 * were moved around the device)165 * obj.description:166 * swipetwo:2:left:down167 * swipetwo:2:left:up168 * swipetwo:2:left:steady169 * swipetwo:2:right:down170 * swipetwo:2:right:up171 * swipetwo:2:right:steady172 *173 * @event 'swipethree'174 * Is triggered after a swipe move gesture with three touchpoints (three175 * fingers were moved around the device)176 * obj.description:177 * swipethree:3:left:down178 * swipethree:3:left:up179 * swipethree:3:left:steady180 * swipethree:3:right:down181 * swipethree:3:right:up182 * swipethree:3:right:steady183 *184 * @event 'swipefour'185 * Is triggered after a swipe move gesture with four touchpoints (four186 * fingers were moved around the device)187 * obj.description:188 * swipefour:4:left:down189 * swipefour:4:left:up190 * swipefour:4:left:steady191 * swipefour:4:right:down192 * swipefour:4:right:up193 * swipefour:4:right:steady194 *195 *196 * @event 'swipeup'197 * Is triggered after an strict upwards swipe move gesture198 * obj.description:199 * swipe:1:steady:up200 * swipe:2:steady:up201 * swipe:3:steady:up202 * swipe:4:steady:up203 *204 * @event 'swiperightup'205 * Is triggered after a rightwards and upwards swipe move gesture206 * obj.description:207 * swipe:1:right:up208 * swipe:2:right:up209 * swipe:3:right:up210 * swipe:4:right:up211 *212 * @event 'swiperight'213 * Is triggered after a strict rightwards swipe move gesture214 * obj.description:215 * swipe:1:right:steady216 * swipe:2:right:steady217 * swipe:3:right:steady218 * swipe:4:right:steady219 *220 * @event 'swiperightdown'221 * Is triggered after a rightwards and downwards swipe move gesture222 * obj.description:223 * swipe:1:right:down224 * swipe:2:right:down225 * swipe:3:right:down226 * swipe:4:right:down227 *228 * @event 'swipedown'229 * Is triggered after a strict downwards swipe move gesture230 * obj.description:231 * swipe:1:steady:down232 * swipe:2:steady:down233 * swipe:3:steady:down234 * swipe:4:steady:down235 *236 * @event 'swipeleftdown'237 * Is triggered after a leftwards and downwards swipe move gesture238 * obj.description:239 * swipe:1:left:down240 * swipe:2:left:down241 * swipe:3:left:down242 * swipe:4:left:down243 *244 * @event 'swipeleft'245 * Is triggered after a strict leftwards swipe move gesture246 * obj.description:247 * swipe:1:left:steady248 * swipe:2:left:steady249 * swipe:3:left:steady250 * swipe:4:left:steady251 *252 * @event 'swipeleftup'253 * Is triggered after a leftwards and upwards swipe move gesture254 * obj.description:255 * swipe:1:left:up256 * swipe:2:left:up257 * swipe:3:left:up258 * swipe:4:left:up259 *260 * @event 'tapone'261 * Is triggered after a single (one finger) tap gesture262 * obj.description:263 * tapone264 *265 * @event 'taptwo'266 * Is triggered after a double (two finger) tap gesture267 * obj.description:268 * taptwo269 * *270 * @event 'tapthree'271 * Is triggered after a tripple (three finger) tap gesture272 * obj.description:273 * tapthree274 *275 *276 * Gestureend events:277 * A gesture is an interpretation of different touchpoints.278 * The jGesture-Events in this group are triggered when a gesture has finished279 * and the touchpoints are removed from the device.280 *281 * @event 'pinchopen'282 * Is triggered when a pinchopen gesture (two fingers moving away from each283 * other) occured and the touchpoints (fingers) are removed the device.284 * obj.description:285 * pinch:+1:open286 *287 * @event 'pinchclose'288 * Is triggered when a pinchclose gesture (two fingers moving towards each289 * other) occured and the touchpoints (fingers) are removed the device.290 * obj.description:291 * pinch:-1:close292 *293 * @event 'rotatecw'294 * Is triggered when a clockwise rotation gesture (two fingers rotating295 * clockwise) occured and the touchpoints (fingers) are removed the device.296 * obj.description:297 * rotate:+1:+clockwise298 *299 * @event 'rotateccw'300 * Is triggered when a counterclockwise rotation gesture (two fingers301 * rotating counterclockwise) occured and the touchpoints (fingers) are302 * removed the device.303 * obj.description:304 * rotate:-1:+counterclockwise305 *306 *307 * Motion events:308 * A "motion event" is an interpretation of changes in space, e.g. a "shaking motion"309 * consists of a specified number of acceleration changes in a given interval.310 * For understanding "directions", place your mobile device on a table with the bottom311 * (home button) close to you:312 * - x-axis: horizontal left / right313 * - y-axis: horizontal front / back (through the home button)314 * - z-axis: vertical through your device315 *316 * Note: Devicemotion / deviceorientation don't send custom event (such as: jGestures.touchstart).317 * Note: Devicemotion should be bound on the "window-element" - because the whole device moves318 *319 * @event 'shake'320 * Is triggered when a shaking motion is detected321 * obj.description:322 * shake:leftright:x-axisfrontback:y-axis:updown:z-axis323 *324 * @event 'shakefrontback'325 * Is triggered when a shaking motion is detected and the gesture can be interpreted as a mainly front-back movement.326 * obj.description:327 * shakefrontback:shakefrontback:y-axis328 *329 * @event 'shakeleftright'330 * Is triggered when a shaking motion is detected and the gesture can be interpreted as a mainly left-right movement.331 * Additional major movements are mentioned in the obj.description.332 * obj.description:333 * shakeleftright:leftright:x-axis334 *335 * @event 'shakeupdown'336 * Is triggered when a shaking motion is detected and the gesture can be interpreted as a mainly up-down movement.337 * Additional major movements are mentioned in the obj.description.338 * obj.description:339 * shake:shakeupdown:updown:z-axis340 *341 * @example342 * .bind( eventType, [ eventData ], handler(eventObject) )343 * jQuery('body').bind('tapone',function(){alert(arguments[1].description);})344 *345 */346 (function($) {347 /**348 * General thresholds.349 */350 // @TODO: move to $...defaults351 // @TODO: shake to defaults freeze etc352 // change of x deg in y ms353 $.jGestures = {};354 $.jGestures.defaults = {};355 $.jGestures.defaults.thresholdShake = {356 requiredShakes : 10,357 freezeShakes: 100,358 frontback : {359 sensitivity: 10360 },361 leftright : {362 sensitivity: 10363 },364 updown : {365 sensitivity: 10366 }367 };368 $.jGestures.defaults.thresholdPinchopen = 0.05;369 $.jGestures.defaults.thresholdPinchmove = 0.05;370 $.jGestures.defaults.thresholdPinch = 0.05;371 $.jGestures.defaults.thresholdPinchclose = 0.05;372 $.jGestures.defaults.thresholdRotatecw = 5; //deg373 $.jGestures.defaults.thresholdRotateccw = 5; // deg374 // a tap becomes a swipe if x/y values changes are above this threshold375 $.jGestures.defaults.thresholdMove = 20;376 $.jGestures.defaults.thresholdSwipe = 100;377 // get capable user agents378 $.jGestures.data = {};379 $.jGestures.data.capableDevicesInUserAgentString = ['iPad','iPhone','iPod','Mobile Safari']; // basic functionality such as swipe, pinch, rotate, tap should work on every mobile safari, e.g. GalaxyTab380 $.jGestures.data.hasGestures = (function () { var _i; for(_i = 0; _i < $.jGestures.data.capableDevicesInUserAgentString.length; _i++ ) { if (navigator.userAgent.indexOf($.jGestures.data.capableDevicesInUserAgentString[_i]) !== -1 ) {return true;} } return false; } )();381 $.hasGestures = $.jGestures.data.hasGestures;382 $.jGestures.events = {383 touchstart : 'jGestures.touchstart',384 touchendStart: 'jGestures.touchend;start',385 touchendProcessed: 'jGestures.touchend;processed',386 gesturestart: 'jGestures.gesturestart',387 gestureendStart: 'jGestures.gestureend;start',388 gestureendProcessed: 'jGestures.gestureend;processed'389 };390 jQuery391 .each({392 // "first domevent necessary"_"touch event+counter" : "exposed as"393 // event: orientationchange394 orientationchange_orientationchange01: "orientationchange",395 // event: gestures396 gestureend_pinchopen01: "pinchopen",397 gestureend_pinchclose01: "pinchclose",398 gestureend_rotatecw01 : 'rotatecw',399 gestureend_rotateccw01 : 'rotateccw',400 // move events401 gesturechange_pinch01: 'pinch',402 gesturechange_rotate01: 'rotate',403 touchstart_swipe13: 'swipemove',404 // event: touches405 touchstart_swipe01: "swipeone",406 touchstart_swipe02: "swipetwo",407 touchstart_swipe03: "swipethree",408 touchstart_swipe04: "swipefour",409 touchstart_swipe05: 'swipeup',410 touchstart_swipe06: 'swiperightup',411 touchstart_swipe07: 'swiperight',412 touchstart_swipe08: 'swiperightdown',413 touchstart_swipe09: 'swipedown',414 touchstart_swipe10: 'swipeleftdown',415 touchstart_swipe11: 'swipeleft',416 touchstart_swipe12: 'swipeleftup',417 touchstart_tap01: 'tapone',418 touchstart_tap02: 'taptwo',419 touchstart_tap03: 'tapthree',420 touchstart_tap04: 'tapfour',421 devicemotion_shake01: 'shake',422 devicemotion_shake02: 'shakefrontback',423 devicemotion_shake03: 'shakeleftright',424 devicemotion_shake04: 'shakeupdown'425 },426 /**427 * Add gesture events inside the jQuery.event.special namespace428 */429 function( sInternal_, sPublicFN_ ) {430 // add as funciton to jQuery.event.special.sPublicFN_431 jQuery.event.special[ sPublicFN_ ] = {432 /**433 * When the first event handler is bound, jQuery executes the setup function.434 * This plugin just uses one eventhandler per element, regardless of the number of bound events.435 * All Events are stored internally as properties on the dom-element using the $.data api.436 * The setup-function adds the eventlistener, acting as a proxy function for the internal events.437 * $.data.ojQueryGestures[_sDOMEvent ('tap') ] = {Boolean}438 * @return {Void}439 */440 setup: function () {441 // split the arguments to necessary controll arguements442 var _aSplit = sInternal_.split('_');443 var _sDOMEvent = _aSplit[0]; //444 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour445 var _sGestureEvent = _aSplit[1].slice(0,_aSplit[1].length-2);446 var _$element = jQuery(this);447 var _oDatajQueryGestures ;448 var oObj;449 // bind the event handler on the first $.bind() for a gestureend-event, set marker450 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {451 // setup pseudo event452 _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};453 oObj = {};454 // marker for: domEvent being set on this element455 // e.g.: $.data.oGestureInternals['touchstart'] = true;456 // since they're grouped, i'm just marking the first one being added457 oObj[_sDOMEvent] = true;458 $.extend(true,_oDatajQueryGestures,oObj);459 _$element.data('ojQueryGestures' ,_oDatajQueryGestures);460 // add gesture events461 if($.hasGestures) {462 switch(_sGestureEvent) {463 // event: orientationchange464 case 'orientationchange':465 _$element.get(0).addEventListener('orientationchange', _onOrientationchange, false);466 break;467 // event:468 // - shake469 // - tilt470 case 'shake':471 case 'shakefrontback':472 case 'shakeleftright':473 case 'shakeupdown':474 case 'tilt':475 //$.hasGyroscope = true //!window.DeviceOrientationEvent;476 //_$element.get(0).addEventListener('devicemotion', _onDevicemotion, false);477 //_$element.get(0).addEventListener('deviceorientation', _onDeviceorientation, false);478 _$element.get(0).addEventListener('devicemotion', _onDevicemotion, false);479 break;480 // event:481 // - touchstart482 // - touchmove483 // - touchend484 case 'tap':485 case 'swipe':486 case 'swipeup':487 case 'swiperightup':488 case 'swiperight':489 case 'swiperightdown':490 case 'swipedown':491 case 'swipeleftdown':492 case 'swipeleft':493 _$element.get(0).addEventListener('touchstart', _onTouchstart, false);494 break;495 // event: gestureend496 case 'pinchopen':497 case 'pinchclose' :498 case 'rotatecw' :499 case 'rotateccw' :500 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);501 _$element.get(0).addEventListener('gestureend', _onGestureend, false);502 break;503 // event: gesturechange504 case 'pinch':505 case 'rotate':506 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);507 _$element.get(0).addEventListener('gesturechange', _onGesturechange, false);508 break;509 }510 }511 // create substitute for gesture events512 else {513 switch(_sGestureEvent) {514 // event substitutes:515 // - touchstart: mousedown516 // - touchmove: none517 // - touchend: mouseup518 case 'tap':519 case 'swipe':520 // _$element.get(0).addEventListener('mousedown', _onTouchstart, false);521 _$element.bind('mousedown', _onTouchstart);522 break;523 // no substitution524 case 'orientationchange':525 case 'pinchopen':526 case 'pinchclose' :527 case 'rotatecw' :528 case 'rotateccw' :529 case 'pinch':530 case 'rotate':531 case 'shake':532 case 'tilt':533 break;534 }535 }536 }537 return false;538 },539 /**540 * For every $.bind(GESTURE) the add-function will be called.541 * Instead of binding an actual eventlister, the event is stored as $.data on the element.542 * The handler will be triggered using $.triggerHandler(GESTURE) if the internal543 * eventhandler (proxy being bound on setup()) detects a GESTURE event544 * @param {Object} event_ jQuery-Event-Object being passed by $.bind()545 * @return {Void}546 */547 add : function(event_) {548 // add pseudo event: properties on $.data549 var _$element = jQuery(this);550 var _oDatajQueryGestures = _$element.data('ojQueryGestures');551// _oDatajQueryGestures[event_.type] = { 'originalType' : event_.type , 'threshold' : event_.data.threshold, 'preventDefault' : event_.data.preventDefault } ;552 _oDatajQueryGestures[event_.type] = { 'originalType' : event_.type } ;553 return false;554 },555 /**556 * For every $.unbind(GESTURE) the remove-function will be called.557 * Instead of removing the actual eventlister, the event is removed from $.data on the element.558 * @param {Object} event_ jQuery-Event-Object being passed by $.bind()559 * @return {Void}560 */561 remove : function(event_) {562 // remove pseudo event: properties on $.data563 var _$element = jQuery(this);564 var _oDatajQueryGestures = _$element.data('ojQueryGestures');565 _oDatajQueryGestures[event_.type] = false;566 _$element.data('ojQueryGestures' ,_oDatajQueryGestures );567 return false;568 },569 /**570 * The last $.unbind()-call on the domElement triggers the teardown function571 * removing the eventlistener572 * @return {Void}573 */574 // @TODO: maybe rework teardown to work with event type?!575 teardown : function() {576 // split the arguments to necessary controll arguements577 var _aSplit = sInternal_.split('_');578 var _sDOMEvent = _aSplit[0]; //579 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour580 var _sGestureEvent = _aSplit[1].slice(0,_aSplit[1].length-2);581 var _$element = jQuery(this);582 var _oDatajQueryGestures;583 var oObj;584 // bind the event handler on the first $.bind() for a gestureend-event, set marker585 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {586 // setup pseudo event587 _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};588 oObj = {};589 // remove marker for: domEvent being set on this element590 oObj[_sDOMEvent] = false;591 $.extend(true,_oDatajQueryGestures,oObj);592 _$element.data('ojQueryGestures' ,_oDatajQueryGestures);593 // remove gesture events594 if($.hasGestures) {595 switch(_sGestureEvent) {596 // event: orientationchange597 case 'orientationchange':598 _$element.get(0).removeEventListener('orientationchange', _onOrientationchange, false);599 break;600 case 'shake':601 case 'shakefrontback':602 case 'shakeleftright':603 case 'shakeupdown':604 case 'tilt':605 _$element.get(0).removeEventListener('devicemotion', _onDevicemotion, false);606 break;607 // event :608 // - touchstart609 // - touchmove610 // - touchend611 case 'tap':612 case 'swipe':613 case 'swipeup':614 case 'swiperightup':615 case 'swiperight':616 case 'swiperightdown':617 case 'swipedown':618 case 'swipeleftdown':619 case 'swipeleft':620 case 'swipeleftup':621 _$element.get(0).removeEventListener('touchstart', _onTouchstart, false);622 _$element.get(0).removeEventListener('touchmove', _onTouchmove, false);623 _$element.get(0).removeEventListener('touchend', _onTouchend, false);624 break;625 // event: gestureend626 case 'pinchopen':627 case 'pinchclose' :628 case 'rotatecw' :629 case 'rotateccw' :630 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);631 _$element.get(0).removeEventListener('gestureend', _onGestureend, false);632 break;633 // event: gesturechange634 case 'pinch':635 case 'rotate':636 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);637 _$element.get(0).removeEventListener('gesturechange', _onGesturechange, false);638 break;639 }640 }641 // remove substitute for gesture events642 else {643 switch(_sGestureEvent) {644 // event substitutes:645 // - touchstart: mousedown646 // - touchmove: none647 // - touchend: mouseup648 case 'tap':649 case 'swipe':650// _$element.get(0).removeEventListener('mousedown', _onTouchstart, false);651// _$element.get(0).removeEventListener('mousemove', _onTouchmove, false);652// _$element.get(0).removeEventListener('mouseup', _onTouchend, false);653 _$element.unbind('mousedown', _onTouchstart);654 _$element.unbind('mousemove', _onTouchmove);655 _$element.unbind('mouseup', _onTouchend);656 break;657 // no substitution658 case 'orientationchange':659 case 'pinchopen':660 case 'pinchclose' :661 case 'rotatecw' :662 case 'rotateccw' :663 case 'pinch':664 case 'rotate':665 case 'shake':666 case 'tilt':667 break;668 }669 }670 }671 return false;672 }673 };674 });675 /**676 * Creates the object that ist passed as second argument to the $element.triggerHandler function.677 * This object contains detailed informations about the gesture event.678 * @param {Object} oOptions_ {type: {String}, touches: {String}, deltaY: {String},deltaX : {String}, startMove: {Object}, event:{DOM-Event}, timestamp:{String},vector: {Number}}679 * @example _createOptions (680 * {681 * type: 'swipemove',682 * touches: '1',683 * deltaY: _iDeltaY,684 * deltaX : _iDeltaX,685 * startMove: _oDatajQueryGestures.oStartTouch,686 * event:event_,687 * timestamp:_oEventData.timestamp,688 * vector: -1689 * }690 * );691 * @returns {Object}692 * {693 * type: eventtype e.g. "swipe","pinch",694 * originalEvent: {DOM-Event},695 * // default: just one entry on the delta-array - the first touchpoint696 * // the first touchpoint is the reference point for every gesture,697 * // because moving touchpoints in various directions would result in698 * // a gesture.699 * // delta and direction details are just provided for touch not for gesture / motion events700 * delta : [701 * {702 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)703 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)704 * moved: {Number}, // distance: relative to the original touchpoint705 * startX: {Number} , // relative to the original touchpoint706 * startY: {Number} ,// relative to the original touchpoint707 * } ],708 * // based on the first touchpoint709 * direction : { // relative to the last touchevent (e.g. touchmove!)710 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)711 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)712 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)713 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)714 * startX: {Number} , //-1,0,+1 relative to the original touchpoint715 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint716 * },717 * rotation: {Number} || null, // gestureonly: amount of rotation relative to the current position NOT the original718 * scale: {Number} || null, // gestureonly: amount of scaling relative to the current position NOT the original719 * duration: {Number}, // ms: relative to the original touchpoint720 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint721 * };722 */723 function _createOptions(oOptions_) {724 // force properties725 oOptions_.startMove = (oOptions_.startMove) ? oOptions_.startMove : {startX: null,startY:null,timestamp:null} ;726 var _iNow = new Date().getTime();727 var _oDirection;728 var _oDelta;729 // calculate touch differences730 if (oOptions_.touches) {731 // store delta values732 _oDelta = [733 {734 lastX: oOptions_.deltaX ,735 lastY: oOptions_.deltaY,736 moved: null,737 startX: oOptions_.screenX - oOptions_.startMove.screenX ,738 startY: oOptions_.screenY - oOptions_.startMove.screenY739 }740 ];741 _oDirection = {742 vector: oOptions_.vector || null,743 orientation : window.orientation || null,744 lastX : ((_oDelta[0].lastX > 0) ? +1 : ( (_oDelta[0].lastX < 0) ? -1 : 0 ) ),745 lastY : ((_oDelta[0].lastY > 0) ? +1 : ( (_oDelta[0].lastY < 0) ? -1 : 0 ) ),746 startX : ((_oDelta[0].startX > 0) ? +1 : ( (_oDelta[0].startX < 0) ? -1 : 0 ) ),747 startY : ((_oDelta[0].startY > 0) ? +1 : ( (_oDelta[0].startY < 0) ? -1 : 0 ) )748 };749 // calculate distance traveled using the pythagorean theorem750 _oDelta[0].moved = Math.sqrt(Math.pow(Math.abs(_oDelta[0].startX), 2) + Math.pow(Math.abs(_oDelta[0].startY), 2));751 }752 return {753 type: oOptions_.type || null,754 originalEvent: oOptions_.event || null,755 delta : _oDelta || null,756 direction : _oDirection || { orientation : window.orientation || null, vector: oOptions_.vector || null},757 duration: (oOptions_.duration) ? oOptions_.duration : ( oOptions_.startMove.timestamp ) ? _iNow - oOptions_.timestamp : null,758 rotation: oOptions_.rotation || null,759 scale: oOptions_.scale || null,760 description : oOptions_.description || [761 oOptions_.type,762 ':',763 oOptions_.touches,764 ':',765 ((_oDelta[0].lastX != 0) ? ((_oDelta[0].lastX > 0) ? 'right' : 'left') : 'steady'),766 ':',767 ((_oDelta[0].lastY != 0) ? ( (_oDelta[0].lastY > 0) ? 'down' : 'up') :'steady')768 ].join('')769 };770 }771 /**772 * DOM-event handlers773 */774 /**775 * Handler: orientationchange776 * Triggers the bound orientationchange handler on the window element777 * The "orientationchange" handler will receive an object with additional information778 * about the event.779 * {780 * direction : {781 * orientation: {-90|0|90|180}782 * },783 * description : [784 * 'orientationchange:{landscape:clockwise:|portrait:default|landscape:counterclockwise|portrait:upsidedown}:{-90|0|90|180}' // e.g. 'orientation:landscape:clockwise:-90785 * }786 * @param {DOM-Event} event_787 * @return {Void}788 */789 function _onOrientationchange(event_) {790 // window.orientation: -90,0,90,180791 var _aDict = ['landscape:clockwise:','portrait:default:','landscape:counterclockwise:','portrait:upsidedown:'];792 $(window).triggerHandler('orientationchange',793 {794 direction : {orientation: window.orientation},795 description : [796 'orientationchange:',797 _aDict[( (window.orientation / 90) +1)],798 window.orientation799 ].join('')800 });801 }802 /**803 * Handler: devicemotion804 * Calculates "motion events" such as shake, tilt, wiggle by observing "changes in space"805 * For understanding "directions", place your mobile device on a table with the bottom806 * (home button) close to you:807 * - x-axis: horizontal left / right808 * - y-axis: horizontal front / back (through the home button)809 * - z-axis: vertical through your device810 * @param {DOM-Event} event_811 * @returns {Object}812 * {813 * type: eventtype e.g. "shake",814 * originalEvent: {DOM-Event},815 * // delta and direction details are just provided for touch not for gesture / motion events816 * delta : null,817 * direction :{818 * vector: null,819 * orientation: -90,0,90,180 || null (window.orienntation)820 * }821 * rotation: {Number} , // amount of rotation relative to the current position NOT the original822 * scale: {Number} , // amount of scaling relative to the current position NOT the original823 * duration: {Number}, // ms: duration of the motion824 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"825 * };826 * @param {DOM-Event} event_827 * @return {Void}828 */829 function _onDevicemotion(event_) {830 var _sType;831 var _$element = jQuery(window);832 //var _bHasGyroscope = $.hasGyroscope;833 // skip custom notification: devicemotion is triggered every 0.05s regardlesse of any gesture834 // get options835 var _oDatajQueryGestures = _$element.data('ojQueryGestures');836 var _oThreshold = $.jGestures.defaults.thresholdShake;837 // get last position or set initital values838 var _oLastDevicePosition = _oDatajQueryGestures.oDeviceMotionLastDevicePosition || {839 accelerationIncludingGravity : {840 x: 0,841 y: 0,842 z: 0843 },844 shake : {845 eventCount: 0,846 intervalsPassed: 0,847 intervalsFreeze: 0848 },849 shakeleftright : {850 eventCount: 0,851 intervalsPassed: 0,852 intervalsFreeze: 0853 },854 shakefrontback : {855 eventCount: 0,856 intervalsPassed: 0,857 intervalsFreeze: 0858 },859 shakeupdown : {860 eventCount: 0,861 intervalsPassed: 0,862 intervalsFreeze: 0863 }864 };865 // cache current values866 var _oCurrentDevicePosition = {867 accelerationIncludingGravity : {868 x: event_.accelerationIncludingGravity.x,869 y: event_.accelerationIncludingGravity.y,870 z: event_.accelerationIncludingGravity.z871 },872 shake: {873 eventCount: _oLastDevicePosition.shake.eventCount,874 intervalsPassed: _oLastDevicePosition.shake.intervalsPassed,875 intervalsFreeze: _oLastDevicePosition.shake.intervalsFreeze876 },877 shakeleftright: {878 eventCount: _oLastDevicePosition.shakeleftright.eventCount,879 intervalsPassed: _oLastDevicePosition.shakeleftright.intervalsPassed,880 intervalsFreeze: _oLastDevicePosition.shakeleftright.intervalsFreeze881 },882 shakefrontback: {883 eventCount: _oLastDevicePosition.shakefrontback.eventCount,884 intervalsPassed: _oLastDevicePosition.shakefrontback.intervalsPassed,885 intervalsFreeze: _oLastDevicePosition.shakefrontback.intervalsFreeze886 },887 shakeupdown: {888 eventCount: _oLastDevicePosition.shakeupdown.eventCount,889 intervalsPassed: _oLastDevicePosition.shakeupdown.intervalsPassed,890 intervalsFreeze: _oLastDevicePosition.shakeupdown.intervalsFreeze891 }892 };893 // options894 var _aType;895 var _aDescription;896 var _oObj;897 // trigger events for all bound pseudo events on this element898 for (_sType in _oDatajQueryGestures) {899 // get current pseudo event900 // trigger bound events on this element901 switch(_sType) {902 case 'shake':903 case 'shakeleftright':904 case 'shakefrontback':905 case 'shakeupdown':906 // options907 _aType = [];908 _aDescription = [];909 _aType.push(_sType);910 // freeze shake - prevent multiple shake events on one shaking motion (user won't stop shaking immediately)911 if (++_oCurrentDevicePosition[_sType].intervalsFreeze > _oThreshold.freezeShakes && _oCurrentDevicePosition[_sType].intervalsFreeze < (2*_oThreshold.freezeShakes) ) { break; }912 // set control values913 _oCurrentDevicePosition[_sType].intervalsFreeze = 0;914 _oCurrentDevicePosition[_sType].intervalsPassed++;915 // check for shaking motions: massive acceleration changes in every direction916 if ( ( _sType === 'shake' ||_sType === 'shakeleftright' ) && ( _oCurrentDevicePosition.accelerationIncludingGravity.x > _oThreshold.leftright.sensitivity || _oCurrentDevicePosition.accelerationIncludingGravity.x < (-1* _oThreshold.leftright.sensitivity) ) ) {917 _aType.push('leftright');918 _aType.push('x-axis');919 }920 if ( ( _sType === 'shake' ||_sType === 'shakefrontback' ) && (_oCurrentDevicePosition.accelerationIncludingGravity.y > _oThreshold.frontback.sensitivity || _oCurrentDevicePosition.accelerationIncludingGravity.y < (-1 * _oThreshold.frontback.sensitivity) ) ) {921 _aType.push('frontback');922 _aType.push('y-axis');923 }924 if ( ( _sType === 'shake' ||_sType === 'shakeupdown' ) && ( _oCurrentDevicePosition.accelerationIncludingGravity.z+9.81 > _oThreshold.updown.sensitivity || _oCurrentDevicePosition.accelerationIncludingGravity.z+9.81 < (-1 * _oThreshold.updown.sensitivity) ) ) {925 _aType.push('updown');926 _aType.push('z-axis');927 }928 // at least one successful shaking event929 if (_aType.length > 1) {930 // minimum number of shaking motions during the defined "time" (messured by events - device event interval: 0.05s)931 if (++_oCurrentDevicePosition[_sType].eventCount == _oThreshold.requiredShakes && (_oCurrentDevicePosition[_sType].intervalsPassed) < _oThreshold.freezeShakes ) {932 // send event933 _$element.triggerHandler(_sType, _createOptions ({type: _sType, description: _aType.join(':'), event:event_,duration:_oCurrentDevicePosition[_sType].intervalsPassed*5 }) );934 // reset935 _oCurrentDevicePosition[_sType].eventCount = 0;936 _oCurrentDevicePosition[_sType].intervalsPassed = 0;937 // freeze shake938 _oCurrentDevicePosition[_sType].intervalsFreeze = _oThreshold.freezeShakes+1;939 }940 // too slow, reset941 else if (_oCurrentDevicePosition[_sType].eventCount == _oThreshold.requiredShakes && (_oCurrentDevicePosition[_sType].intervalsPassed) > _oThreshold.freezeShakes ) {942 _oCurrentDevicePosition[_sType].eventCount = 0 ;943 _oCurrentDevicePosition[_sType].intervalsPassed = 0;944 }945 }946 break;947 }948 // refresh pseudo events949 _oObj = {};950 _oObj.oDeviceMotionLastDevicePosition = _oCurrentDevicePosition;951 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));952 }953 }954 /**955 * Handler: touchstart or mousedown956 * Setup pseudo-event by storing initial values such as :957 * screenX : {Number}958 * screenY : {Number}959 * timestamp: {Number}960 * on the pseudo gesture event and961 * sets up additional eventlisteners for handling touchmove events.962 * @param {DOM-Event} event_963 * @return {Void}964 */965 function _onTouchstart(event_) {966 // ignore bubbled handlers967 // if ( event_.currentTarget !== event_.target ) { return; }968 var _$element = jQuery(event_.currentTarget);969 // var _$element = jQuery(event_.target);970 // trigger custom notification971 _$element.triggerHandler($.jGestures.events.touchstart,event_);972 // set the necessary touch events973 if($.hasGestures) {974 event_.currentTarget.addEventListener('touchmove', _onTouchmove, false);975 event_.currentTarget.addEventListener('touchend', _onTouchend, false);976 }977 // event substitution978 else {979// event_.currentTarget.addEventListener('mousemove', _onTouchmove, false);980// event_.currentTarget.addEventListener('mouseup', _onTouchend, false);981 _$element.bind('mousemove', _onTouchmove);982 _$element.bind('mouseup', _onTouchend);983 }984 // get stored pseudo event985 var _oDatajQueryGestures = _$element.data('ojQueryGestures');986 // var _oEventData = _oDatajQueryGestures[_sType];987 var _eventBase = (event_.touches) ? event_.touches[0] : event_;988 // store current values for calculating relative values (changes between touchmoveevents)989 var _oObj = {};990 _oObj.oLastSwipemove = { screenX : _eventBase.screenX, screenY : _eventBase.screenY, timestamp:new Date().getTime()};991 _oObj.oStartTouch = { screenX : _eventBase.screenX, screenY : _eventBase.screenY, timestamp:new Date().getTime()};992 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));993 }994 /**995 * Handler: touchmove or mousemove996 * Calculates the x/y changes since the last event,997 * compares it to $.jGestures.defaults.thresholdMove and triggers998 * an swipemove event if the distance exceed the999 * threshold.1000 * Custom-event argument object:1001 * {Object}1002 * {1003 * type: e.g. 'swipemove',1004 * â: {DOM-Event},1005 * // default: just one entry on the delta-array - the first touchpoint1006 * // the first touchpoint is the reference point for every gesture,1007 * // because moving touchpoints in various directions would result in1008 * // a gesture.1009 * // delta and direction details are just provided for touch not for gesture / motion events1010 * delta : [1011 * {1012 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)1013 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)1014 * moved: {Number}, // distance: relative to the original touchpoint1015 * startX: {Number} , // relative to the original touchpoint1016 * startY: {Number} ,// relative to the original touchpoint1017 * } ],1018 * // based on the first touchpoint1019 * direction : { // relative to the last touchevent (e.g. touchmove!)1020 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1021 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1022 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1023 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1024 * startX: {Number} , //-1,0,+1 relative to the original touchpoint1025 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint1026 * },1027 * rotation: null, // gestureonly: amount of rotation relative to the current position NOT the original1028 * scale: null, // gestureonly: amount of scaling relative to the current position NOT the original1029 * duration: {Number}, // ms: relative to the original touchpoint1030 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint1031 * };1032 *1033 * @param {DOM-Event} event_1034 * @return {Void}1035 */1036 function _onTouchmove(event_) {1037 var _$element = jQuery(event_.currentTarget);1038 // var _$element = jQuery(event_.target);1039 // get stored pseudo event1040 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1041 var _bHasTouches = !!event_.touches;1042 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;1043 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;1044 //relative to the last event1045 var _oEventData = _oDatajQueryGestures.oLastSwipemove;1046 var _iDeltaX = _iScreenX - _oEventData.screenX ;1047 var _iDeltaY = _iScreenY - _oEventData.screenY;1048 var _oDetails;1049 // there's a swipemove set (not the first occurance), trigger event1050 if (!!_oDatajQueryGestures.oLastSwipemove) {1051 // check1052 _oDetails = _createOptions({type: 'swipemove', touches: (_bHasTouches) ? event_.touches.length: '1', screenY: _iScreenY,screenX:_iScreenX ,deltaY: _iDeltaY,deltaX : _iDeltaX, startMove:_oEventData, event:event_, timestamp:_oEventData.timestamp});1053 _$element.triggerHandler(_oDetails.type,_oDetails);1054 }1055 // store the new values1056 var _oObj = {};1057 var _eventBase = (event_.touches) ? event_.touches[0] : event_;1058 _oObj.oLastSwipemove = { screenX : _eventBase.screenX, screenY : _eventBase.screenY, timestamp:new Date().getTime()};1059 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1060 }1061 /**1062 * Handler: touchend or mouseup1063 * Removes the additional handlers (move/end)1064 * Calculates the x/y changes since the touchstart event1065 * not in relation to the last move event.1066 * Triggers the1067 * swipeone|swipetwo|swipethree|swipefour|1068 * swipeup|swiperightup|swiperight|swiperightdown|swipedown|1069 * swipeleftdown|swipeleft|swipeleftup|1070 * tapone|taptwo|tapthree|tapfour1071 * event.1072 * {Object}1073 * {1074 * type: eventtype e.g. "swipeone","swipeleftdown",1075 * originalEvent: {DOM-Event},1076 * // default: just one entry on the delta-array - the first touchpoint1077 * // the first touchpoint is the reference point for every gesture,1078 * // because moving touchpoints in various directions would result in1079 * // a gesture.1080 * // delta and direction details are just provided for touch not for gesture / motion events1081 * delta : [1082 * {1083 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)1084 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)1085 * moved: {Number}, // distance: relative to the original touchpoint1086 * startX: {Number} , // relative to the original touchpoint1087 * startY: {Number} ,// relative to the original touchpoint1088 * } ],1089 * // based on the first touchpoint1090 * direction : { // relative to the last touchevent (e.g. touchmove!)1091 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1092 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1093 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1094 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1095 * startX: {Number} , //-1,0,+1 relative to the original touchpoint1096 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint1097 * },1098 * rotation: null,1099 * scale: null ,1100 * duration: {Number}, // ms: relative to the original touchpoint1101 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint1102 * };1103 * @param {DOM-Event} event_1104 * @return {Void}1105 */1106 function _onTouchend(event_) {1107 // ignore bubbled handlers1108 // if ( event_.currentTarget !== event_.target ) { return; }1109 var _$element = jQuery(event_.currentTarget);1110 var _bHasTouches = !!event_.changedTouches;1111 var _iTouches = (_bHasTouches) ? event_.changedTouches.length : '1';1112 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;1113 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;1114 // trigger custom notification1115 _$element.triggerHandler($.jGestures.events.touchendStart,event_);1116 // var _$element = jQuery(event_.target);1117 // remove events1118 if($.hasGestures) {1119 event_.currentTarget.removeEventListener('touchmove', _onTouchmove, false);1120 event_.currentTarget.removeEventListener('touchend', _onTouchend, false);1121 }1122 // event substitution1123 else {1124// event_.currentTarget.removeEventListener('mousemove', _onTouchmove, false);1125// event_.currentTarget.removeEventListener('mouseup', _onTouchend, false);1126 _$element.unbind('mousemove', _onTouchmove);1127 _$element.unbind('mouseup', _onTouchend);1128 }1129 // get all bound pseudo events1130 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1131 // if the current change on the x/y position is above the defined threshold for moving an element set the moved flag1132 // to distinguish between a moving gesture and a shaking finger trying to tap1133 var _bHasMoved = (1134 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdMove ||1135 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdMove1136 ) ? true : false;1137 // if the current change on the x/y position is above the defined threshold for swiping set the moved flag1138 // to indicate we're dealing with a swipe gesture1139 var _bHasSwipeGesture = (1140 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdSwipe ||1141 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdSwipe1142 ) ? true : false;1143 var _sType;1144 var _oEventData ;1145 var _oDelta;1146 // calculate distances in relation to the touchstart position not the last touchmove event!1147 var _iDeltaX;1148 var _iDeltaY;1149 var _oDetails;1150 var _aDict = ['zero','one','two','three','four'];1151 // swipe marker1152 var _bIsSwipe;1153 // trigger events for all bound pseudo events on this element1154 for (_sType in _oDatajQueryGestures) {1155 // get current pseudo event1156 _oEventData = _oDatajQueryGestures.oStartTouch;1157 _oDelta = {};1158 _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;1159 _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;1160 // calculate distances in relation to the touchstart position not the last touchmove event!1161 _iDeltaX = _iScreenX - _oEventData.screenX ;1162 _iDeltaY = _iScreenY - _oEventData.screenY;1163 _oDetails = _createOptions({type: 'swipe', touches: _iTouches, screenY: _iScreenY,screenX:_iScreenX ,deltaY: _iDeltaY,deltaX : _iDeltaX, startMove:_oEventData, event:event_, timestamp: _oEventData.timestamp });1164 // swipe marker1165 _bIsSwipe = false;1166 // trigger bound events on this element1167 switch(_sType) {1168 case 'swipeone':1169 if( _bHasTouches === false && _iTouches == 1 && _bHasMoved === false){1170 // trigger tapone!1171 break;1172 }1173 if (_bHasTouches===false || ( _iTouches == 1 && _bHasMoved === true && _bHasSwipeGesture===true)) {1174 _bIsSwipe = true;1175 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1176 _$element.triggerHandler(_oDetails.type,_oDetails);1177 }1178 break;1179 case 'swipetwo':1180 if (( _bHasTouches && _iTouches== 2 && _bHasMoved === true && _bHasSwipeGesture===true)) {1181 _bIsSwipe = true;1182 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1183 _$element.triggerHandler(_oDetails.type,_oDetails);1184 }1185 break;1186 case 'swipethree':1187 if ( ( _bHasTouches && _iTouches == 3 && _bHasMoved === true && _bHasSwipeGesture===true)) {1188 _bIsSwipe = true;1189 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1190 _$element.triggerHandler(_oDetails.type,_oDetails);1191 }1192 break;1193 case 'swipefour':1194 if ( ( _bHasTouches && _iTouches == 4 && _bHasMoved === true && _bHasSwipeGesture===true)) {1195 _bIsSwipe = true;1196 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1197 _$element.triggerHandler(_oDetails.type,_oDetails);1198 }1199 break;1200 case 'swipeup':1201 case 'swiperightup':1202 case 'swiperight':1203 case 'swiperightdown':1204 case 'swipedown':1205 case 'swipeleftdown':1206 case 'swipeleft':1207 case 'swipeleftup':1208 if ( _bHasTouches && _bHasMoved === true && _bHasSwipeGesture===true) {1209 _bIsSwipe = true;1210 _oDetails.type = [1211 'swipe',1212 ((_oDetails.delta[0].lastX != 0) ? ((_oDetails.delta[0].lastX > 0) ? 'right' : 'left') : ''),1213 ((_oDetails.delta[0].lastY != 0) ? ((_oDetails.delta[0].lastY > 0) ? 'down' : 'up') :'')1214 ].join('');1215 _$element.triggerHandler(_oDetails.type, _oDetails);1216 }1217 break;1218 case 'tapone':1219 case 'taptwo':1220 case 'tapthree':1221 case 'tapfour':1222 if (( /* _bHasTouches && */ _bHasMoved !== true && _bIsSwipe !==true) && (_aDict[_iTouches] ==_sType.slice(3)) ) {1223 _oDetails.description = ['tap',_aDict[_iTouches]].join('');1224 _oDetails.type = ['tap',_aDict[_iTouches]].join('');1225 _$element.triggerHandler(_oDetails.type,_oDetails);1226 }1227 break;1228 }1229 // refresh pseudo events1230 var _oObj = {};1231// _oObj[_sType] = false;1232// _oObj.hasTouchmoved = false;1233 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1234 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1235 }1236 _$element.triggerHandler($.jGestures.events.touchendProcessed,event_);1237 }1238 /**1239 * Handler: gesturestart1240 * Setup pseudo-event by storing initial values such as :1241 * timestamp: {Number}1242 * on the pseudo gesture event1243 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1244 * @param {DOM-Event} event_1245 * @return {Void}1246 */1247 function _onGesturestart(event_) {1248 // ignore bubbled handlers1249 // if ( event_.currentTarget !== event_.target ) { return; }1250 var _$element = jQuery(event_.currentTarget);1251 // var _$element = jQuery(event_.target);1252 // trigger custom notification1253 _$element.triggerHandler($.jGestures.events.gesturestart,event_);1254 // get stored pseudo event1255 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1256 // var _oEventData = _oDatajQueryGestures[_sType];1257 // store current values for calculating relative values (changes between touchmoveevents)1258 var _oObj = {};1259 _oObj.oStartTouch = {timestamp:new Date().getTime()};1260 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1261 }1262 /**1263 * Handler: gesturechange1264 * Read the event_.scale / event_.rotate values,1265 * an triggers a pinch|rotate event if necessary.1266 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1267 * @returns {Object}1268 * {1269 * type: eventtype e.g. "pinch","rotate",1270 * originalEvent: {DOM-Event},1271 * // delta and direction details are just provided for touch not for gesture / motion events1272 * delta : null,1273 * direction : {1274 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1275 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1276 * },1277 * rotation: {Number} , // amount of rotation relative to the current position NOT the original1278 * scale: {Number} , // amount of scaling relative to the current position NOT the original1279 * duration: {Number}, // ms: relative to the original touchpoint1280 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1281 * };1282 * @param {DOM-Event} event_1283 * @return {Void}1284 */1285 function _onGesturechange(event_) {1286 // ignore bubbled handlers1287 // if ( event_.currentTarget !== event_.target ) { return; }1288 var _$element = jQuery(event_.currentTarget);1289 // var _$element = jQuery(event_.target);1290 var _iDelta,_iDirection,_sDesc,_oDetails;1291 // get all pseudo events1292 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1293 // trigger events for all bound pseudo events on this element1294 var _sType;1295 for (_sType in _oDatajQueryGestures) {1296 // trigger a specific bound event1297 switch(_sType) {1298 case 'pinch':1299 _iDelta = event_.scale;1300 if ( ( ( _iDelta < 1 ) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose) ) || ( ( _iDelta > 1 ) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen) ) ) {1301 _iDirection = (_iDelta < 1 ) ? -1 : +1 ;1302 _oDetails = _createOptions({type: 'pinch', scale: _iDelta, touches: null,startMove:_oDatajQueryGestures.oStartTouch, event:event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, vector:_iDirection, description: ['pinch:',_iDirection,':' , ( (_iDelta < 1 ) ? 'close' : 'open' )].join('') });1303 _$element.triggerHandler(_oDetails.type, _oDetails);1304 }1305 break;1306 case 'rotate':1307 _iDelta = event_.rotation;1308 if ( ( ( _iDelta < 1 ) && ( -1*(_iDelta) > $.jGestures.defaults.thresholdRotateccw ) ) || ( ( _iDelta > 1 ) && (_iDelta > $.jGestures.defaults.thresholdRotatecw) ) ) {1309 _iDirection = (_iDelta < 1 ) ? -1 : +1 ;1310 _oDetails = _createOptions({type: 'rotate', rotation: _iDelta, touches: null, startMove:_oDatajQueryGestures.oStartTouch, event:event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, vector:_iDirection, description: ['rotate:',_iDirection,':' , ( (_iDelta < 1 ) ? 'counterclockwise' : 'clockwise' )].join('') });1311 _$element.triggerHandler(_oDetails.type, _oDetails);1312 }1313 break;1314 }1315 }1316 }1317 /**1318 * Handler: gestureend1319 * Read the event_.scale / event_.rotate values,1320 * compares it to $.jGestures.defaults.threshold* and triggers1321 * a pinchclose|pinchclose|rotatecw|rotateccw event if the distance exceed the1322 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1323 * * Custom-event argument object:1324 * @returns {Object}1325 * {1326 * type: eventtype e.g. "pinchclose","pinchopen", "rotatecw", "rotateccw",1327 * originalEvent: {DOM-Event},1328 * // delta and direction details are just provided for touch not for gesture / motion events1329 * delta : null,1330 * // based on the first touchpoint1331 * direction : {1332 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1333 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1334 * },1335 * rotation: {Number} , // amount of rotation relative to the current position NOT the original1336 * scale: {Number} , // amount of scaling relative to the current position NOT the original1337 * duration: {Number}, // ms: relative to the original touchpoint1338 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1339 * };1340 * @param {DOM-Event} event_1341 * @return {Void}1342 */1343 function _onGestureend(event_) {1344 // ignore bubbled handlers1345 // if ( event_.currentTarget !== event_.target ) { return; }1346 var _$element = jQuery(event_.currentTarget);1347 // var _$element = jQuery(event_.target);1348 // trigger custom notification1349 _$element.triggerHandler($.jGestures.events.gestureendStart,event_);1350 var _iDelta;1351 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1352 // trigger handler for every bound event1353 var _sType;1354 for (_sType in _oDatajQueryGestures) {1355 switch(_sType) {1356 case 'pinchclose':1357 _iDelta = event_.scale;1358 if (( _iDelta < 1 ) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose)) {1359 _$element.triggerHandler('pinchclose', _createOptions ({type: 'pinchclose', scale:_iDelta, vector: -1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event:event_, timestamp:_oDatajQueryGestures.oStartTouch.timestamp,description: 'pinch:-1:close' }) );1360 }1361 break;1362 case 'pinchopen':1363 _iDelta = event_.scale;1364 if ( ( _iDelta > 1 ) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen) ) {1365 _$element.triggerHandler('pinchopen', _createOptions ({type: 'pinchopen', scale:_iDelta, vector: +1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event:event_, timestamp:_oDatajQueryGestures.oStartTouch.timestamp,description: 'pinch:+1:open'}) );1366 }1367 break;1368 case 'rotatecw':1369 _iDelta = event_.rotation;1370 if ( ( _iDelta > 1 ) && (_iDelta > $.jGestures.defaults.thresholdRotatecw) ) {1371 _$element.triggerHandler('rotatecw', _createOptions ({type: 'rotatecw', rotation:_iDelta, vector: +1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event:event_, timestamp:_oDatajQueryGestures.oStartTouch.timestamp,description: 'rotate:+1:clockwise'}) );1372 }1373 break;1374 case 'rotateccw':1375 _iDelta = event_.rotation;1376 if ( ( _iDelta < 1 ) && ( -1*(_iDelta) > $.jGestures.defaults.thresholdRotateccw ) ) {1377 _$element.triggerHandler('rotateccw', _createOptions ({type: 'rotateccw', rotation:_iDelta, vector: -1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event:event_, timestamp:_oDatajQueryGestures.oStartTouch.timestamp,description: 'rotate:-1:counterclockwise'}) );1378 }1379 break;1380 }1381 }1382 _$element.triggerHandler($.jGestures.events.gestureendProcessed,event_);1383 }1384 }1385)(jQuery);...
jquery.jgestures.js
Source:jquery.jgestures.js
1/**2 * jGestures: a jQuery plugin for gesture events 3 * Copyright 2010-2011, Neue Digitale / Razorfish GmbH4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 * 14 * @fileOverview15 * Neue Digitale / Razorfish GmbH javascript library: add touch events such as 'pinch', 16 * 'rotate', 'swipe', 'tap' and 'orientationchange' on capable user agents. 17 * For incapable devices there's a basic event substitution: a "tapone" event 18 * can be triggered by "clicking", a "swipeone" by performing a swipe-ish 19 * gesture using the mouse (buttondown - mousemove - buttonup).20 * 21 * This is still a beta version, bugfixes and improvements appreciated.22 * 23 * @author martin.krause@neue-digitale.de24 * @version 0.8725 *26 * @snvauthor $Author: martinkr $27 * @svnversion $Revision: 0 $28 *29 * @requires 30 * jQuery JavaScript Library v1.4.2 - http://jquery.com/31 * Copyright 2010, John Resig32 * Dual licensed under the MIT or GPL Version 2 licenses.33 * http://jquery.org/license34 *35 * 36 * @copyright Neue Digitale / Razorfish GmbH37 * 38 * @example jQuery('#swipe').bind('swipeone',eventHandler);39 * 40 * Notification on native events:41 * On every native touchstart, touchend, gesturestart and gestureend-event, 42 * jgestures triggers a corresponding custom event 43 * (jGestures.touchstart,jGestures.touchend,jGestures.gesturestart and jGestures.gestureend) on the event-element.44 * The eventhandler's second argument represents the original touch event (yes: including all touchpoints).45 * Use this if you need very detailed control e.g. kinetic scrolling or implementing additional gestures.46 * 47 * Every jGesture-eventhandler receives a custom object as second argument 48 * containing the original event (originalEvent property) and processed 49 * information (such as delta values and timesptamp).50 * Example:{ 51 * type: eventtype e.g. "swipe","pinch", 52 originalEvent: {DOM-Event},53* // default: just one entry on the delta-array - the first touchpoint54* // the first touchpoint is the reference point for every gesture, 55* // because moving touchpoints in various directions would result in 56* // a gesture.57* // delta and direction details are just provided for touch not for gesture events58* delta : [ 59* {60* lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)61* lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)62* moved: {Number}, // distance: relative to the original touchpoint 63* startX: {Number} , // relative to the original touchpoint64* startY: {Number} ,// relative to the original touchpoint65* } ],66* // based on the first touchpoint67* direction : { // relative to the last touchevent (e.g. touchmove!)68* vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)69* orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)70* lastX : {Number}, // -1,0,+1 || null (orientationchange) // relative to the last touchevent (e.g. touchmove!)71* lastY : {Number}, // -1,0,+1 || null (orientationchange)// relative to the last touchevent (e.g. touchmove!)72* startX: {Number} , // relative to the original touchpoint73* startY: {Number} ,// relative to the original touchpoint74* },75* rotation: {Number} || {null}, // gestureonly: amount of rotation relative to the current position NOT the original 76* scale: {Number} || {null}, // gestureonly: amount of scaling relative to the current position NOT the original 77* duration: {Number}, // ms: relative to the original touchpoint 78* description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint79* };80 * 81 * Available jGesture-events can be grouped into: 82 *83 * 84 * Device events:85 * The jGesture-Events in this group are triggered by the device.86 * 87 * @event 'orientationchange'88 * The device is turned clockwise or counterclockwise. This event is triggered 89 * by the device and might use an internal gyroscope.90 * obj.description:91 * orientationchange:landscape:clockwise:-9092 * orientationchange:portrait:default:093 * orientationchange:landscape:counterclockwise|portrait:9094 * orientationchange:portrait:upsidedown:18095 *96 *97 * Move events:98 * The jGesture-Events in this group are triggered during the touch/gesture 99 * execution whenever a touchpoint changes. 100 * In contrast to touchend/gestureend-events which are triggered after 101 * the touch/gesture has completed. 102 *103 * @event 'pinch'104 * Is triggered during a pinch gesture (two fingers moving away from or 105 * towards each other).106 * obj.description:107 * pinch:-1:close108 * pinch:+1:open109 * 110 * @event 'rotate'111 * Is triggered during a rotation gesture (two fingers rotating clockwise 112 * or counterclockwise).113 * obj.description:114 * rotate:-1:counterclockwise115 * rotate:+1:+clockwise116 * 117 * @event 'swipemove'118 * Is triggered during a swipe move gesture (finger(s) being moved around 119 * the device, e.g. dragging)120 * obj.description:121 * swipemove:1:left:down122 * swipemove:1:left:up123 * swipemove:1:left:steady124 * swipemove:1:right:down125 * swipemove:1:right:up126 * swipemove:1:right:steady127 * swipemove:2:left:down128 * swipemove:2:left:up129 * swipemove:2:left:steady130 * swipemove:2:right:down131 * swipemove:2:right:up132 * swipemove:2:right:steady133 * swipemove:2:left:down134 * swipemove:3:left:up135 * swipemove:3:left:steady136 * swipemove:3:right:down137 * swipemove:3:right:up138 * swipemove:3:right:steady139 * swipemove:3:left:down140 * swipemove:4:left:up141 * swipemove:4:left:steady142 * swipemove:4:right:down143 * swipemove:4:right:up144 * swipemove:4:right:steady145 *146 * 147 * Toucheend events:148 * The jGesture-Events in this group are triggered after the touch/gesture 149 * has completed. 150 * In contrast to touchmove-events which are triggered during the touch/gesture 151 * execution whenever a touchpoint changes.152 * 153 * @event 'swipeone'154 * Is triggered after a swipe move gesture with one touchpoint (one finger155 * was moved around the device)156 * obj.description:157 * swipeone:1:left:down158 * swipeone:1:left:up159 * swipeone:1:left:steady160 * swipeone:1:right:down161 * swipeone:1:right:up162 * swipeone:1:right:steady163 * 164 * @event 'swipetwo'165 * Is triggered after a swipe move gesture with two touchpoints (two fingers166 * were moved around the device)167 * obj.description:168 * swipetwo:2:left:down169 * swipetwo:2:left:up170 * swipetwo:2:left:steady171 * swipetwo:2:right:down172 * swipetwo:2:right:up173 * swipetwo:2:right:steady174 * 175 * @event 'swipethree'176 * Is triggered after a swipe move gesture with three touchpoints (three 177 * fingers were moved around the device)178 * obj.description:179 * swipethree:3:left:down180 * swipethree:3:left:up181 * swipethree:3:left:steady182 * swipethree:3:right:down183 * swipethree:3:right:up184 * swipethree:3:right:steady185 * 186 * @event 'swipefour'187 * Is triggered after a swipe move gesture with four touchpoints (four 188 * fingers were moved around the device)189 * obj.description:190 * swipefour:4:left:down191 * swipefour:4:left:up192 * swipefour:4:left:steady193 * swipefour:4:right:down194 * swipefour:4:right:up195 * swipefour:4:right:steady196 * 197 * 198 * @event 'swipeup'199 * Is triggered after an strict upwards swipe move gesture 200 * obj.description:201 * swipe:1:steady:up202 * swipe:2:steady:up203 * swipe:3:steady:up204 * swipe:4:steady:up205 *206 * @event 'swiperightup'207 * Is triggered after a rightwards and upwards swipe move gesture 208 * obj.description:209 * swipe:1:right:up210 * swipe:2:right:up211 * swipe:3:right:up212 * swipe:4:right:up 213 * 214 * @event 'swiperight'215 * Is triggered after a strict rightwards swipe move gesture 216 * obj.description:217 * swipe:1:right:steady218 * swipe:2:right:steady219 * swipe:3:right:steady220 * swipe:4:right:steady221 * 222 * @event 'swiperightdown'223 * Is triggered after a rightwards and downwards swipe move gesture 224 * obj.description:225 * swipe:1:right:down226 * swipe:2:right:down227 * swipe:3:right:down228 * swipe:4:right:down229 * 230 * @event 'swipedown'231 * Is triggered after a strict downwards swipe move gesture 232 * obj.description:233 * swipe:1:steady:down234 * swipe:2:steady:down235 * swipe:3:steady:down236 * swipe:4:steady:down237 * 238 * @event 'swipeleftdown'239 * Is triggered after a leftwards and downwards swipe move gesture 240 * obj.description:241 * swipe:1:left:down242 * swipe:2:left:down243 * swipe:3:left:down244 * swipe:4:left:down245 * 246 * @event 'swipeleft'247 * Is triggered after a strict leftwards swipe move gesture 248 * obj.description:249 * swipe:1:left:steady250 * swipe:2:left:steady251 * swipe:3:left:steady252 * swipe:4:left:steady253 * 254 * @event 'swipeleftup'255 * Is triggered after a leftwards and upwards swipe move gesture 256 * obj.description:257 * swipe:1:left:up258 * swipe:2:left:up259 * swipe:3:left:up260 * swipe:4:left:up261 * 262 * @event 'tapone'263 * Is triggered after a single (one finger) tap gesture 264 * obj.description:265 * tapone266* 267 * @event 'taptwo'268 * Is triggered after a double (two finger) tap gesture 269 * obj.description:270 * taptwo271 * * 272 * @event 'tapthree'273 * Is triggered after a tripple (three finger) tap gesture 274 * obj.description:275 * tapthree276 * 277 * 278 * Gestureend events:279 * A gesture is an interpretation of different touchpoints. 280 * The jGesture-Events in this group are triggered when a gesture has finished 281 * and the touchpoints are removed from the device.282 *283 * @event 'pinchopen'284 * Is triggered when a pinchopen gesture (two fingers moving away from each 285 * other) occured and the touchpoints (fingers) are removed the device. 286 * obj.description:287 * pinch:+1:open288 * 289 * @event 'pinchclose'290 * Is triggered when a pinchclose gesture (two fingers moving towards each 291 * other) occured and the touchpoints (fingers) are removed the device. 292 * obj.description:293 * pinch:-1:close294 * 295 * @event 'rotatecw'296 * Is triggered when a clockwise rotation gesture (two fingers rotating 297 * clockwise) occured and the touchpoints (fingers) are removed the device.298 * obj.description:299 * rotate:+1:+clockwise300 * 301 * @event 'rotateccw'302 * Is triggered when a counterclockwise rotation gesture (two fingers 303 * rotating counterclockwise) occured and the touchpoints (fingers) are 304 * removed the device.305 * obj.description:306 * rotate:-1:+counterclockwise307 * 308 * @example309 * .bind( eventType, [ eventData ], handler(eventObject) )310 * jQuery('body').bind('tapone',function(){alert(arguments[1].description);})311 312313 */314315 (function ($) {316317 /**318 * General thresholds.319 */320 $.jGestures = {};321 $.jGestures.defaults = {};322 $.jGestures.defaults.thresholdPinchopen = 0.05;323 $.jGestures.defaults.thresholdPinchmove = 0.05;324 $.jGestures.defaults.thresholdPinch = 0.05;325 $.jGestures.defaults.thresholdPinchclose = 0.05;326 $.jGestures.defaults.thresholdRotatecw = 5; //deg327 $.jGestures.defaults.thresholdRotateccw = 5; // deg328 // a tap becomes a swipe if x/y values changes are above this threshold 329 $.jGestures.defaults.thresholdMove = 20;330 $.jGestures.defaults.thresholdSwipe = 100;331 $.jGestures.data = {};332 // get capable user agents 333 $.jGestures.data.capableDevicesInUserAgentString = ['iPad', 'iPhone', 'iPod', 'Mobile Safari']; // basic functionality such as swipe, pinch, rotate, tap should work on every mobile safari, e.g. GalaxyTab 334 $.jGestures.data.hasGestures = (function () { var _i; for (_i = 0; _i < $.jGestures.data.capableDevicesInUserAgentString.length; _i++) { if (navigator.userAgent.indexOf($.jGestures.data.capableDevicesInUserAgentString[_i]) !== -1) { return true; } } return false; })();335 $.hasGestures = $.jGestures.data.hasGestures;336 $.jGestures.events = {337 touchstart: 'jGestures.touchstart',338 touchendStart: 'jGestures.touchend;start',339 touchendProcessed: 'jGestures.touchend;processed',340 gesturestart: 'jGestures.gesturestart',341 gestureendStart: 'jGestures.gestureend;start',342 gestureendProcessed: 'jGestures.gestureend;processed'343 };344345 jQuery346 .each({347 // "first domevent necessary"_"touch event+counter" : "exposed as"348 // event: orientationchange349 orientationchange_orientationchange01: "orientationchange",350 // event: gestures351 gestureend_pinchopen01: "pinchopen",352 gestureend_pinchclose01: "pinchclose",353 gestureend_rotatecw01: 'rotatecw',354 gestureend_rotateccw01: 'rotateccw',355 // move events356 gesturechange_pinch01: 'pinch',357 gesturechange_rotate01: 'rotate',358 touchstart_swipe13: 'swipemove',359 // event: touches360 touchstart_swipe01: "swipeone",361 touchstart_swipe02: "swipetwo",362 touchstart_swipe03: "swipethree",363 touchstart_swipe04: "swipefour",364 touchstart_swipe05: 'swipeup',365 touchstart_swipe06: 'swiperightup',366 touchstart_swipe07: 'swiperight',367 touchstart_swipe08: 'swiperightdown',368 touchstart_swipe09: 'swipedown',369 touchstart_swipe10: 'swipeleftdown',370 touchstart_swipe11: 'swipeleft',371 touchstart_swipe12: 'swipeleftup',372 touchstart_tap01: 'tapone',373 touchstart_tap02: 'taptwo',374 touchstart_tap03: 'tapthree',375 touchstart_tap04: 'tapfour'376 },377378 /**379 * Add gesture events inside the jQuery.event.special namespace 380 */381 function (sInternal_, sPublicFN_) {382383 // add as funciton to jQuery.event.special.sPublicFN_ 384 jQuery.event.special[sPublicFN_] = {385386 /**387 * When the first event handler is bound, jQuery executes the setup function.388 * This plugin just uses one eventhandler per element, regardless of the number of bound events.389 * All Events are stored internally as properties on the dom-element using the $.data api. 390 * The setup-function adds the eventlistener, acting as a proxy function for the internal events.391 * $.data.ojQueryGestures[_sDOMEvent ('tap') ] = {Boolean}392 * @return {Void}393 */394 setup: function () {395396 // split the arguments to necessary controll arguements397 var _aSplit = sInternal_.split('_');398 var _sDOMEvent = _aSplit[0]; // 399 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour400 var _sGestureEvent = _aSplit[1].slice(0, _aSplit[1].length - 2);401 var _$element = jQuery(this);402 // bind the event handler on the first $.bind() for a gestureend-event, set marker403 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {404 // setup pseudo event405 var _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};406 var oObj = {};407 // marker for: domEvent being set on this element 408 // e.g.: $.data.oGestureInternals['touchstart'] = true;409 // since they're grouped, i'm just marking the first one being added410 oObj[_sDOMEvent] = true;411 $.extend(true, _oDatajQueryGestures, oObj);412 _$element.data('ojQueryGestures', _oDatajQueryGestures);413 // add gesture events414 if ($.hasGestures) {415 switch (_sGestureEvent) {416417 // event: orientationchange 418 case 'orientationchange':419 _$element.get(0).addEventListener('orientationchange', _onOrientationchange, false);420 break;421422 // event: 423 // - touchstart 424 // - touchmove 425 // - touchend 426 case 'tap':427 case 'swipe':428 case 'swipeup':429 case 'swiperightup':430 case 'swiperight':431 case 'swiperightdown':432 case 'swipedown':433 case 'swipeleftdown':434 case 'swipeleft':435 _$element.get(0).addEventListener('touchstart', _onTouchstart, false);436 break;437438 // event: gestureend 439 case 'pinchopen':440 case 'pinchclose':441 case 'rotatecw':442 case 'rotateccw':443 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);444 _$element.get(0).addEventListener('gestureend', _onGestureend, false);445 break;446447 // event: gesturechange 448 case 'pinch':449 case 'rotate':450 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);451 _$element.get(0).addEventListener('gesturechange', _onGesturechange, false);452 break;453 }454 }455 // create substitute for gesture events 456 else {457 switch (_sGestureEvent) {458 // event substitutes: 459 // - touchstart: mousedown 460 // - touchmove: none 461 // - touchend: mouseup 462 case 'tap':463 case 'swipe':464 // _$element.get(0).addEventListener('mousedown', _onTouchstart, false);465 _$element.bind('mousedown', _onTouchstart);466 break;467468 // no substitution 469 case 'orientationchange':470 case 'pinchopen':471 case 'pinchclose':472 case 'rotatecw':473 case 'rotateccw':474 case 'pinch':475 case 'rotate':476477 break;478 }479 }480481 }482 return false;483 },484485 /**486 * For every $.bind(GESTURE) the add-function will be called.487 * Instead of binding an actual eventlister, the event is stored as $.data on the element.488 * The handler will be triggered using $.triggerHandler(GESTURE) if the internal 489 * eventhandler (proxy being bound on setup()) detects a GESTURE event490 * @param {Object} event_ jQuery-Event-Object being passed by $.bind() 491 * @return {Void}492 */493 add: function (event_) {494 // add pseudo event: properties on $.data 495 var _$element = jQuery(this);496 var _oDatajQueryGestures = _$element.data('ojQueryGestures');497 // _oDatajQueryGestures[event_.type] = { 'originalType' : event_.type , 'threshold' : event_.data.threshold, 'preventDefault' : event_.data.preventDefault } ;498 _oDatajQueryGestures[event_.type] = { 'originalType': event_.type };499 return false;500 },501502 /**503 * For every $.unbind(GESTURE) the remove-function will be called.504 * Instead of removing the actual eventlister, the event is removed from $.data on the element.505 * @param {Object} event_ jQuery-Event-Object being passed by $.bind() 506 * @return {Void}507 */508 remove: function (event_) {509 // remove pseudo event: properties on $.data 510 var _$element = jQuery(this);511 var _oDatajQueryGestures = _$element.data('ojQueryGestures');512 _oDatajQueryGestures[event_.type] = false;513 _$element.data('ojQueryGestures', _oDatajQueryGestures);514 return false;515 },516517 /**518 * The last $.unbind()-call on the domElement triggers the teardown function 519 * removing the eventlistener520 * @return {Void}521 */522 // @TASK: maybe rework teardown to work with event type?!523 teardown: function () {524 // split the arguments to necessary controll arguements525 var _aSplit = sInternal_.split('_');526 var _sDOMEvent = _aSplit[0]; // 527 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour528 var _sGestureEvent = _aSplit[1].slice(0, _aSplit[1].length - 2);529 var _$element = jQuery(this);530 // bind the event handler on the first $.bind() for a gestureend-event, set marker531 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {532 // setup pseudo event533 var _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};534 var oObj = {};535 // remove marker for: domEvent being set on this element 536 oObj[_sDOMEvent] = false;537 $.extend(true, _oDatajQueryGestures, oObj);538 _$element.data('ojQueryGestures', _oDatajQueryGestures);539540 // remove gesture events541 if ($.hasGestures) {542 switch (_sGestureEvent) {543544 // event: orientationchange 545 case 'orientationchange':546 _$element.get(0).removeEventListener('orientationchange', _onOrientationchange, false);547 break;548549 // event : 550 // - touchstart 551 // - touchmove 552 // - touchend 553 case 'tap':554 case 'swipe':555 case 'swipeup':556 case 'swiperightup':557 case 'swiperight':558 case 'swiperightdown':559 case 'swipedown':560 case 'swipeleftdown':561 case 'swipeleft':562 case 'swipeleftup':563 _$element.get(0).removeEventListener('touchstart', _onTouchstart, false);564 _$element.get(0).removeEventListener('touchmove', _onTouchmove, false);565 _$element.get(0).removeEventListener('touchend', _onTouchend, false);566 break;567568 // event: gestureend 569 case 'pinchopen':570 case 'pinchclose':571 case 'rotatecw':572 case 'rotateccw':573 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);574 _$element.get(0).removeEventListener('gestureend', _onGestureend, false);575 break;576577 // event: gesturechange 578 case 'pinch':579 case 'rotate':580 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);581 _$element.get(0).removeEventListener('gesturechange', _onGesturechange, false);582 break;583 }584 }585 // remove substitute for gesture events 586 else {587 switch (_sGestureEvent) {588 // event substitutes: 589 // - touchstart: mousedown 590 // - touchmove: none 591 // - touchend: mouseup 592 case 'tap':593 case 'swipe':594 // _$element.get(0).removeEventListener('mousedown', _onTouchstart, false);595 // _$element.get(0).removeEventListener('mousemove', _onTouchmove, false);596 // _$element.get(0).removeEventListener('mouseup', _onTouchend, false);597 _$element.unbind('mousedown', _onTouchstart);598 _$element.unbind('mousemove', _onTouchmove);599 _$element.unbind('mouseup', _onTouchend);600 break;601602 // no substitution 603 case 'orientationchange':604 case 'pinchopen':605 case 'pinchclose':606 case 'rotatecw':607 case 'rotateccw':608 case 'pinch':609 case 'rotate':610611 break;612 }613 }614615 }616 return false;617 }618619 };620 });621622 /**623 * Creates the object that ist passed as second argument to the $element.triggerHandler function.624 * This object contains detailed informations about the gesture event.625 * @param {Object} oOptions_ {type: {String}, touches: {String}, deltaY: {String},deltaX : {String}, startMove: {Object}, event:{DOM-Event}, timestamp:{String},vector: {Number}}626 * @example _createOptions (627 * { 628 * type: 'swipemove', 629 * touches: '1', 630 * deltaY: _iDeltaY,631 * deltaX : _iDeltaX, 632 * startMove: _oDatajQueryGestures.oStartTouch, 633 * event:event_, 634 * timestamp:_oEventData.timestamp,635 * vector: -1636 * }637 * );638 * @returns {Object} 639 * {640 * type: eventtype e.g. "swipe","pinch",641 * originalEvent: {DOM-Event},642 * // default: just one entry on the delta-array - the first touchpoint643 * // the first touchpoint is the reference point for every gesture, 644 * // because moving touchpoints in various directions would result in 645 * // a gesture.646 * // delta and direction details are just provided for touch not for gesture events647 * delta : [ 648 * {649 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)650 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)651 * moved: {Number}, // distance: relative to the original touchpoint 652 * startX: {Number} , // relative to the original touchpoint653 * startY: {Number} ,// relative to the original touchpoint654 * } ],655 * // based on the first touchpoint656 * direction : { // relative to the last touchevent (e.g. touchmove!)657 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)658 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)659 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)660 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)661 * startX: {Number} , //-1,0,+1 relative to the original touchpoint662 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint663 * },664 * rotation: {Number} || {null}, // gestureonly: amount of rotation relative to the current position NOT the original 665 * scale: {Number} || {null}, // gestureonly: amount of scaling relative to the current position NOT the original 666 * duration: {Number}, // ms: relative to the original touchpoint 667 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint668 * };669 */670 function _createOptions(oOptions_) {671 // force properties672 oOptions_.startMove = (oOptions_.startMove) ? oOptions_.startMove : { startX: null, startY: null, timestamp: null };673 var _iNow = new Date().getTime();674675 // calculate touch differences 676 if (oOptions_.touches) {677 // store delta values678 var _oDelta = [679 {680 lastX: oOptions_.deltaX,681 lastY: oOptions_.deltaY,682 moved: null,683 startX: oOptions_.screenX - oOptions_.startMove.screenX,684 startY: oOptions_.screenY - oOptions_.startMove.screenY685 }686 ];687688 var _oDirection = {689 vector: oOptions_.vector,690 orientation: window.orientation || null,691 lastX: ((_oDelta[0].lastX > 0) ? +1 : ((_oDelta[0].lastX < 0) ? -1 : 0)),692 lastY: ((_oDelta[0].lastY > 0) ? +1 : ((_oDelta[0].lastY < 0) ? -1 : 0)),693 startX: ((_oDelta[0].startX > 0) ? +1 : ((_oDelta[0].startX < 0) ? -1 : 0)),694 startY: ((_oDelta[0].startY > 0) ? +1 : ((_oDelta[0].startY < 0) ? -1 : 0))695 };696697 // calculate distance traveled using the pythagorean theorem 698 _oDelta[0].moved = Math.sqrt(Math.pow(Math.abs(_oDelta[0].startX), 2) + Math.pow(Math.abs(_oDelta[0].startY), 2));699700 }701 return {702 type: oOptions_.type || null,703 originalEvent: oOptions_.event || null,704 delta: _oDelta || null,705 direction: _oDirection || { orientation: window.orientation || null, vector: oOptions_.vector || null },706 duration: (oOptions_.startMove.timestamp) ? _iNow - oOptions_.timestamp : null,707 rotation: oOptions_.rotation || null,708 scale: oOptions_.scale || null,709 description: oOptions_.description || [710 oOptions_.type,711 ':',712 oOptions_.touches,713 ':',714 ((_oDelta[0].lastX != 0) ? ((_oDelta[0].lastX > 0) ? 'right' : 'left') : 'steady'),715 ':',716 ((_oDelta[0].lastY != 0) ? ((_oDelta[0].lastY > 0) ? 'down' : 'up') : 'steady')717 ].join('')718 };719720 }721722723724 /**725 * DOM-event handlers726 */727728 /**729 * Handler: orientationchange730 * Triggers the bound orientationchange handler on the window element731 * The "orientationchange" handler will receive an object with additional information732 * about the event.733 * {734 * direction : {735 * orientation: {-90|0|90|180}736 * },737 * description : [738 * 'orientationchange:{landscape:clockwise:|portrait:default|landscape:counterclockwise|portrait:upsidedown}:{-90|0|90|180}' // e.g. 'orientation:landscape:clockwise:-90739 * }740 * @param {DOM-Event} event_741 * @return {Void}742 */743 function _onOrientationchange(event_) {744745 // window.orientation: -90,0,90,180746 var _aDict = ['landscape:clockwise:', 'portrait:default:', 'landscape:counterclockwise:', 'portrait:upsidedown:'];747748 $(window).triggerHandler('orientationchange',749 {750 direction: { orientation: window.orientation },751 description: [752 'orientationchange:',753 _aDict[((window.orientation / 90) + 1)],754 window.orientation755 ].join('')756 });757 }758759760 /**761 * Handler: touchstart or mousedown762 * Setup pseudo-event by storing initial values such as :763 * screenX : {Number}764 * screenY : {Number}765 * timestamp: {Number}766 * on the pseudo gesture event and 767 * sets up additional eventlisteners for handling touchmove events.768 * @param {DOM-Event} event_769 * @return {Void}770 */771 function _onTouchstart(event_) {772773 // ignore bubbled handlers774 // if ( event_.currentTarget !== event_.target ) { return; }775776 var _$element = jQuery(event_.currentTarget);777 // var _$element = jQuery(event_.target); 778779 // trigger custom notification780 _$element.triggerHandler($.jGestures.events.touchstart, event_);781782783 // set the necessary touch events784 if ($.hasGestures) {785 event_.currentTarget.addEventListener('touchmove', _onTouchmove, false);786 event_.currentTarget.addEventListener('touchend', _onTouchend, false);787 }788 // event substitution789 else {790 // event_.currentTarget.addEventListener('mousemove', _onTouchmove, false);791 // event_.currentTarget.addEventListener('mouseup', _onTouchend, false);792 _$element.bind('mousemove', _onTouchmove);793 _$element.bind('mouseup', _onTouchend);794 }795796 // get stored pseudo event797 var _oDatajQueryGestures = _$element.data('ojQueryGestures');798799 // var _oEventData = _oDatajQueryGestures[_sType];800 var _eventBase = (event_.touches) ? event_.touches[0] : event_;801 // store current values for calculating relative values (changes between touchmoveevents)802 var _oObj = {};803 _oObj.oLastSwipemove = { screenX: _eventBase.screenX, screenY: _eventBase.screenY, timestamp: new Date().getTime() };804 _oObj.oStartTouch = { screenX: _eventBase.screenX, screenY: _eventBase.screenY, timestamp: new Date().getTime() };805806 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));807 }808809810 /**811 * Handler: touchmove or mousemove812 * Calculates the x/y changes since the last event, 813 * compares it to $.jGestures.defaults.thresholdMove and triggers 814 * an swipemove event if the distance exceed the 815 * threshold.816 * Custom-event argument object: 817 * {Object} 818 * {819 * type: e.g. 'swipemove',820 * â: {DOM-Event},821 * // default: just one entry on the delta-array - the first touchpoint822 * // the first touchpoint is the reference point for every gesture, 823 * // because moving touchpoints in various directions would result in 824 * // a gesture.825 * // delta and direction details are just provided for touch not for gesture events826 * delta : [ 827 * {828 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)829 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)830 * moved: {Number}, // distance: relative to the original touchpoint 831 * startX: {Number} , // relative to the original touchpoint832 * startY: {Number} ,// relative to the original touchpoint833 * } ],834 * // based on the first touchpoint835 * direction : { // relative to the last touchevent (e.g. touchmove!)836 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)837 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)838 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)839 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)840 * startX: {Number} , //-1,0,+1 relative to the original touchpoint841 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint842 * },843 * rotation: {null}, // gestureonly: amount of rotation relative to the current position NOT the original 844 * scale: {null}, // gestureonly: amount of scaling relative to the current position NOT the original 845 * duration: {Number}, // ms: relative to the original touchpoint 846 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint847 * };848 * description : {String} // details as String: swipemove:1:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipemove:1:left:steady"849 * };850 * @param {DOM-Event} event_851 * @return {Void}852 */853 function _onTouchmove(event_) {854855 var _$element = jQuery(event_.currentTarget);856 // var _$element = jQuery(event_.target); 857858 // get stored pseudo event859 var _oDatajQueryGestures = _$element.data('ojQueryGestures');860861 var _bHasTouches = !!event_.touches;862 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;863 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;864865 //relative to the last event866 var _oEventData = _oDatajQueryGestures.oLastSwipemove;867 var _iDeltaX = _iScreenX - _oEventData.screenX;868 var _iDeltaY = _iScreenY - _oEventData.screenY;869870 // there's a swipemove set (not the first occurance), trigger event 871 if (!!_oDatajQueryGestures.oLastSwipemove) {872 // check 873 var _oDetails = _createOptions({ type: 'swipemove', touches: (_bHasTouches) ? event_.touches.length : '1', screenY: _iScreenY, screenX: _iScreenX, deltaY: _iDeltaY, deltaX: _iDeltaX, startMove: _oEventData, event: event_, timestamp: _oEventData.timestamp });874 _$element.triggerHandler(_oDetails.type, _oDetails);875 }876 // store the new values877 var _oObj = {};878 var _eventBase = (event_.touches) ? event_.touches[0] : event_;879 _oObj.oLastSwipemove = { screenX: _eventBase.screenX, screenY: _eventBase.screenY, timestamp: new Date().getTime() };880 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));881 }882883884 /**885 * Handler: touchend or mouseup886 * Removes the additional handlers (move/end)887 * Calculates the x/y changes since the touchstart event888 * not in relation to the last move event.889 * Triggers the 890 * swipeone|swipetwo|swipethree|swipefour|891 * swipeup|swiperightup|swiperight|swiperightdown|swipedown|892 * swipeleftdown|swipeleft|swipeleftup|893 * tapone|taptwo|tapthree|tapfour 894 * event.895 * {Object} 896 * {897 * type: eventtype e.g. "swipeone","swipeleftdown",898 * originalEvent: {DOM-Event},899 * // default: just one entry on the delta-array - the first touchpoint900 * // the first touchpoint is the reference point for every gesture, 901 * // because moving touchpoints in various directions would result in 902 * // a gesture.903 * // delta and direction details are just provided for touch not for gesture events904 * delta : [ 905 * {906 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)907 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)908 * moved: {Number}, // distance: relative to the original touchpoint 909 * startX: {Number} , // relative to the original touchpoint910 * startY: {Number} ,// relative to the original touchpoint911 * } ],912 * // based on the first touchpoint913 * direction : { // relative to the last touchevent (e.g. touchmove!)914 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)915 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)916 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)917 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)918 * startX: {Number} , //-1,0,+1 relative to the original touchpoint919 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint920 * },921 * rotation: {null}, 922 * scale: {null} , 923 * duration: {Number}, // ms: relative to the original touchpoint 924 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint925 * };926 * @param {DOM-Event} event_927 * @return {Void}928 */929 function _onTouchend(event_) {930931 // ignore bubbled handlers932 // if ( event_.currentTarget !== event_.target ) { return; }933934 var _$element = jQuery(event_.currentTarget);935 var _bHasTouches = !!event_.changedTouches;936 var _iTouches = (_bHasTouches) ? event_.changedTouches.length : '1';937 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;938 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;939940 // trigger custom notification941 _$element.triggerHandler($.jGestures.events.touchendStart, event_);942943 // var _$element = jQuery(event_.target); 944 // remove events945 if ($.hasGestures) {946 event_.currentTarget.removeEventListener('touchmove', _onTouchmove, false);947 event_.currentTarget.removeEventListener('touchend', _onTouchend, false);948 }949 // event substitution950 else {951 // event_.currentTarget.removeEventListener('mousemove', _onTouchmove, false);952 // event_.currentTarget.removeEventListener('mouseup', _onTouchend, false);953 _$element.unbind('mousemove', _onTouchmove);954 _$element.unbind('mouseup', _onTouchend);955 }956 // get all bound pseudo events957 var _oDatajQueryGestures = _$element.data('ojQueryGestures');958959 // if the current change on the x/y position is above the defined threshold for moving an element set the moved flag 960 // to distinguish between a moving gesture and a shaking finger trying to tap961 var _bHasMoved = (962 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdMove ||963 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdMove964 ) ? true : false;965966 // if the current change on the x/y position is above the defined threshold for swiping set the moved flag 967 // to indicate we're dealing with a swipe gesture968 var _bHasSwipeGesture = (969 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdSwipe ||970 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdSwipe971 ) ? true : false;972973974 var _sType;975 // trigger events for all bound pseudo events on this element 976 for (_sType in _oDatajQueryGestures) {977978 // get current pseudo event979 var _oEventData = _oDatajQueryGestures.oStartTouch;980981 var _oDelta = {};982 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;983 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;984 // calculate distances in relation to the touchstart position not the last touchmove event!985 var _iDeltaX = _iScreenX - _oEventData.screenX;986 var _iDeltaY = _iScreenY - _oEventData.screenY;987 var _oDetails = _createOptions({ type: 'swipe', touches: _iTouches, screenY: _iScreenY, screenX: _iScreenX, deltaY: _iDeltaY, deltaX: _iDeltaX, startMove: _oEventData, event: event_, timestamp: _oEventData.timestamp });988989 var _aDict = ['zero', 'one', 'two', 'three', 'four'];990991 // swipe marker992 var _bIsSwipe = false;993994 // trigger bound events on this element995 switch (_sType) {996 case 'swipeone':997998 if (_bHasTouches === false && _iTouches == 1 && _bHasMoved === false) {999 // trigger tapone!1000 break;1001 }1002 if (_bHasTouches === false || (_iTouches == 1 && _bHasMoved === true && _bHasSwipeGesture === true)) {1003 _bIsSwipe = true;10041005 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1006 _$element.triggerHandler(_oDetails.type, _oDetails);1007 }1008 break;10091010 case 'swipetwo':1011 if ((_bHasTouches && _iTouches == 2 && _bHasMoved === true && _bHasSwipeGesture === true)) {1012 _bIsSwipe = true;1013 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1014 _$element.triggerHandler(_oDetails.type, _oDetails);1015 }1016 break;10171018 case 'swipethree':1019 if ((_bHasTouches && _iTouches == 3 && _bHasMoved === true && _bHasSwipeGesture === true)) {1020 _bIsSwipe = true;1021 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1022 _$element.triggerHandler(_oDetails.type, _oDetails);1023 }1024 break;10251026 case 'swipefour':1027 if ((_bHasTouches && _iTouches == 4 && _bHasMoved === true && _bHasSwipeGesture === true)) {1028 _bIsSwipe = true;1029 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1030 _$element.triggerHandler(_oDetails.type, _oDetails);1031 }1032 break;10331034 case 'swipeup':1035 case 'swiperightup':1036 case 'swiperight':1037 case 'swiperightdown':1038 case 'swipedown':1039 case 'swipeleftdown':1040 case 'swipeleft':1041 case 'swipeleftup':1042 if (_bHasTouches && _bHasMoved === true && _bHasSwipeGesture === true) {1043 _bIsSwipe = true;1044 _oDetails.type = [1045 'swipe',1046 ((_oDetails.delta[0].lastX != 0) ? ((_oDetails.delta[0].lastX > 0) ? 'right' : 'left') : ''),1047 ((_oDetails.delta[0].lastY != 0) ? ((_oDetails.delta[0].lastY > 0) ? 'down' : 'up') : '')1048 ].join('');1049 if (_sType == _oDetails.type) {1050 _$element.triggerHandler(_oDetails.type, _oDetails);1051 }1052 }1053 break;10541055 case 'tapone':1056 case 'taptwo':1057 case 'tapthree':1058 case 'tapfour':1059 if (( /* _bHasTouches && */_bHasMoved !== true && _bIsSwipe !== true) && (_aDict[_iTouches] == _sType.slice(3))) {1060 _oDetails.description = ['tap', _aDict[_iTouches]].join('');1061 _oDetails.type = ['tap', _aDict[_iTouches]].join('');1062 _$element.triggerHandler(_oDetails.type, _oDetails);1063 }1064 break;10651066 }10671068 // refresh pseudo events1069 var _oObj = {};1070 // _oObj[_sType] = false;1071 // _oObj.hasTouchmoved = false;1072 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));1073 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));10741075 }1076 _$element.triggerHandler($.jGestures.events.touchendProcessed, event_);1077 }107810791080 /**1081 * Handler: gesturestart1082 * Setup pseudo-event by storing initial values such as :1083 * timestamp: {Number}1084 * on the pseudo gesture event1085 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated 1086 * @param {DOM-Event} event_1087 * @return {Void}1088 */1089 function _onGesturestart(event_) {10901091 // ignore bubbled handlers1092 // if ( event_.currentTarget !== event_.target ) { return; }10931094 var _$element = jQuery(event_.currentTarget);1095 // var _$element = jQuery(event_.target); 10961097 // trigger custom notification1098 _$element.triggerHandler($.jGestures.events.gesturestart, event_);109911001101 // get stored pseudo event1102 var _oDatajQueryGestures = _$element.data('ojQueryGestures');11031104 // var _oEventData = _oDatajQueryGestures[_sType];1105 // store current values for calculating relative values (changes between touchmoveevents)1106 var _oObj = {};1107 _oObj.oStartTouch = { timestamp: new Date().getTime() };1108 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));1109 }11101111 /**1112 * Handler: gesturechange1113 * Read the event_.scale / event_.rotate values,1114 * an triggers a pinch|rotate event if necessary.1115 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1116 * @returns {Object} 1117 * {1118 * type: eventtype e.g. "pinch","rotate",1119 * originalEvent: {DOM-Event},1120 * // delta and direction details are just provided for touch not for gesture events1121 * delta : null,1122 * direction :null,1123 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1124 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1125 * rotation: {Number} , // amount of rotation relative to the current position NOT the original 1126 * scale: {Number} , // amount of scaling relative to the current position NOT the original 1127 * duration: {Number}, // ms: relative to the original touchpoint 1128 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1129 * };1130 * @param {DOM-Event} event_1131 * @return {Void}1132 */1133 function _onGesturechange(event_) {11341135 // ignore bubbled handlers1136 // if ( event_.currentTarget !== event_.target ) { return; }11371138 var _$element = jQuery(event_.currentTarget);1139 // var _$element = jQuery(event_.target); 1140 var _iDelta, _iDirection, _sDesc, _oDetails;1141 // get all pseudo events1142 var _oDatajQueryGestures = _$element.data('ojQueryGestures');11431144 // trigger events for all bound pseudo events on this element1145 var _sType;1146 for (_sType in _oDatajQueryGestures) {11471148 // trigger a specific bound event1149 switch (_sType) {11501151 case 'pinch':1152 _iDelta = event_.scale;1153 if (((_iDelta < 1) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose)) || ((_iDelta > 1) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen))) {1154 _iDirection = (_iDelta < 1) ? -1 : +1;1155 _oDetails = _createOptions({ type: 'pinch', scale: _iDelta, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, vector: _iDirection, description: ['pinch:', _iDirection, ':', ((_iDelta < 1) ? 'close' : 'open')].join('') });1156 _$element.triggerHandler(_oDetails.type, _oDetails);1157 }1158 break;11591160 case 'rotate':1161 _iDelta = event_.rotation;1162 if (((_iDelta < 1) && (-1 * (_iDelta) > $.jGestures.defaults.thresholdRotateccw)) || ((_iDelta > 1) && (_iDelta > $.jGestures.defaults.thresholdRotatecw))) {1163 _iDirection = (_iDelta < 1) ? -1 : +1;1164 _oDetails = _createOptions({ type: 'rotate', rotation: _iDelta, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, vector: _iDirection, description: ['rotate:', _iDirection, ':', ((_iDelta < 1) ? 'counterclockwise' : 'clockwise')].join('') });1165 _$element.triggerHandler(_oDetails.type, _oDetails);1166 }1167 break;11681169 }1170 }11711172 }117311741175 /**1176 * Handler: gestureend1177 * Read the event_.scale / event_.rotate values,1178 * compares it to $.jGestures.defaults.threshold* and triggers 1179 * a pinchclose|pinchclose|rotatecw|rotateccw event if the distance exceed the 1180 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1181 * * Custom-event argument object: 1182 * @returns {Object} 1183 * {1184 * type: eventtype e.g. "pinchclose","pinchopen", "rotatecw", "rotateccw",1185 * originalEvent: {DOM-Event},1186 * // delta and direction details are just provided for touch not for gesture events1187 * delta : null,1188 * // based on the first touchpoint1189 * direction : null // relative to the last touchevent (e.g. touchmove!)1190 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1191 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1192 * rotation: {Number} , // amount of rotation relative to the current position NOT the original 1193 * scale: {Number} , // amount of scaling relative to the current position NOT the original 1194 * duration: {Number}, // ms: relative to the original touchpoint 1195 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1196 * };1197 * @param {DOM-Event} event_1198 * @return {Void}1199 */1200 function _onGestureend(event_) {1201 // ignore bubbled handlers1202 // if ( event_.currentTarget !== event_.target ) { return; }12031204 var _$element = jQuery(event_.currentTarget);1205 // var _$element = jQuery(event_.target);12061207 // trigger custom notification1208 _$element.triggerHandler($.jGestures.events.gestureendStart, event_);12091210 var _iDelta;1211 var _oDatajQueryGestures = _$element.data('ojQueryGestures');12121213 // trigger handler for every bound event1214 var _sType;1215 for (_sType in _oDatajQueryGestures) {12161217 switch (_sType) {12181219 case 'pinchclose':1220 _iDelta = event_.scale;1221 if ((_iDelta < 1) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose)) {1222 _$element.triggerHandler('pinchclose', _createOptions({ type: 'pinchclose', scale: _iDelta, vector: -1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'pinch:-1:close' }));1223 }1224 break;12251226 case 'pinchopen':1227 _iDelta = event_.scale;1228 if ((_iDelta > 1) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen)) {1229 _$element.triggerHandler('pinchopen', _createOptions({ type: 'pinchopen', scale: _iDelta, vector: +1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'pinch:+1:open' }));1230 }1231 break;12321233 case 'rotatecw':1234 _iDelta = event_.rotation;1235 if ((_iDelta > 1) && (_iDelta > $.jGestures.defaults.thresholdRotatecw)) {1236 _$element.triggerHandler('rotatecw', _createOptions({ type: 'rotatecw', rotation: _iDelta, vector: +1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'rotate:+1:clockwise' }));1237 }1238 break;12391240 case 'rotateccw':1241 _iDelta = event_.rotation;1242 if ((_iDelta < 1) && (-1 * (_iDelta) > $.jGestures.defaults.thresholdRotateccw)) {1243 _$element.triggerHandler('rotateccw', _createOptions({ type: 'rotateccw', rotation: _iDelta, vector: -1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'rotate:-1:counterclockwise' }));1244 }1245 break;12461247 }1248 }1249 _$element.triggerHandler($.jGestures.events.gestureendProcessed, event_);1250 }1251 }
...
jgestures.js
Source:jgestures.js
1/**2 * jGestures: a jQuery plugin for gesture events3 * Copyright 2010-2011 Neue Digitale / Razorfish GmbH4 * Copyright 2011-2012, Razorfish GmbH5 * Licensed under the Apache License, Version 2.0 (the "License");6 * you may not use this file except in compliance with the License.7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.08 * Unless required by applicable law or agreed to in writing, software9 * distributed under the License is distributed on an "AS IS" BASIS,10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11 * See the License for the specific language governing permissions and12 * limitations under the License.13 * @copyright Razorfish GmbH14 * @author martin.krause@razorfish.de15 * @version 0.90-shake16 * @requires jQuery JavaScript Library v1.4.2 - http://jquery.com/- Copyright 2010, John Resig- Dual licensed under the MIT or GPL Version 2 licenses. http://jquery.org/license17 */18(function(c) {19 c.jGestures = {};20 c.jGestures.defaults = {};21 c.jGestures.defaults.thresholdShake = {22 requiredShakes: 10,23 freezeShakes: 100,24 frontback: {25 sensitivity: 1026 },27 leftright: {28 sensitivity: 1029 },30 updown: {31 sensitivity: 1032 }33 };34 c.jGestures.defaults.thresholdPinchopen = 0.05;35 c.jGestures.defaults.thresholdPinchmove = 0.05;36 c.jGestures.defaults.thresholdPinch = 0.05;37 c.jGestures.defaults.thresholdPinchclose = 0.05;38 c.jGestures.defaults.thresholdRotatecw = 5;39 c.jGestures.defaults.thresholdRotateccw = 5;40 c.jGestures.defaults.thresholdMove = 20;41 c.jGestures.defaults.thresholdSwipe = 100;42 c.jGestures.data = {};43 c.jGestures.data.capableDevicesInUserAgentString = ["iPad", "iPhone", "iPod", "Mobile Safari"];44 c.jGestures.data.hasGestures = (function() {45 var k;46 for (k = 0; k < c.jGestures.data.capableDevicesInUserAgentString.length; k++) {47 if (navigator.userAgent.indexOf(c.jGestures.data.capableDevicesInUserAgentString[k]) !== -1) {48 return true49 }50 }51 return false52 })();53 c.hasGestures = c.jGestures.data.hasGestures;54 c.jGestures.events = {55 touchstart: "jGestures.touchstart",56 touchendStart: "jGestures.touchend;start",57 touchendProcessed: "jGestures.touchend;processed",58 gesturestart: "jGestures.gesturestart",59 gestureendStart: "jGestures.gestureend;start",60 gestureendProcessed: "jGestures.gestureend;processed"61 };62 jQuery.each({63 orientationchange_orientationchange01: "orientationchange",64 gestureend_pinchopen01: "pinchopen",65 gestureend_pinchclose01: "pinchclose",66 gestureend_rotatecw01: "rotatecw",67 gestureend_rotateccw01: "rotateccw",68 gesturechange_pinch01: "pinch",69 gesturechange_rotate01: "rotate",70 touchstart_swipe13: "swipemove",71 touchstart_swipe01: "swipeone",72 touchstart_swipe02: "swipetwo",73 touchstart_swipe03: "swipethree",74 touchstart_swipe04: "swipefour",75 touchstart_swipe05: "swipeup",76 touchstart_swipe06: "swiperightup",77 touchstart_swipe07: "swiperight",78 touchstart_swipe08: "swiperightdown",79 touchstart_swipe09: "swipedown",80 touchstart_swipe10: "swipeleftdown",81 touchstart_swipe11: "swipeleft",82 touchstart_swipe12: "swipeleftup",83 touchstart_tap01: "tapone",84 touchstart_tap02: "taptwo",85 touchstart_tap03: "tapthree",86 touchstart_tap04: "tapfour",87 devicemotion_shake01: "shake",88 devicemotion_shake02: "shakefrontback",89 devicemotion_shake03: "shakeleftright",90 devicemotion_shake04: "shakeupdown"91 },92 function(l, k) {93 jQuery.event.special[k] = {94 setup: function() {95 var r = l.split("_");96 var o = r[0];97 var m = r[1].slice(0, r[1].length - 2);98 var p = jQuery(this);99 var q;100 var n;101 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {102 q = p.data("ojQueryGestures") || {};103 n = {};104 n[o] = true;105 c.extend(true, q, n);106 p.data("ojQueryGestures", q);107 if (c.hasGestures) {108 switch (m) {109 case "orientationchange":110 p.get(0).addEventListener("orientationchange", a, false);111 break;112 case "shake":113 case "shakefrontback":114 case "shakeleftright":115 case "shakeupdown":116 case "tilt":117 p.get(0).addEventListener("devicemotion", b, false);118 break;119 case "tap":120 case "swipe":121 case "swipeup":122 case "swiperightup":123 case "swiperight":124 case "swiperightdown":125 case "swipedown":126 case "swipeleftdown":127 case "swipeleft":128 p.get(0).addEventListener("touchstart", h, false);129 break;130 case "pinchopen":131 case "pinchclose":132 case "rotatecw":133 case "rotateccw":134 p.get(0).addEventListener("gesturestart", e, false);135 p.get(0).addEventListener("gestureend", i, false);136 break;137 case "pinch":138 case "rotate":139 p.get(0).addEventListener("gesturestart", e, false);140 p.get(0).addEventListener("gesturechange", f, false);141 break142 }143 } else {144 switch (m) {145 case "tap":146 case "swipe":147 p.bind("mousedown", h);148 break;149 case "orientationchange":150 case "pinchopen":151 case "pinchclose":152 case "rotatecw":153 case "rotateccw":154 case "pinch":155 case "rotate":156 case "shake":157 case "tilt":158 break159 }160 }161 }162 return false163 },164 add: function(n) {165 var m = jQuery(this);166 var o = m.data("ojQueryGestures");167 o[n.type] = {168 originalType: n.type169 };170 return false171 },172 remove: function(n) {173 var m = jQuery(this);174 var o = m.data("ojQueryGestures");175 o[n.type] = false;176 m.data("ojQueryGestures", o);177 return false178 },179 teardown: function() {180 var r = l.split("_");181 var o = r[0];182 var m = r[1].slice(0, r[1].length - 2);183 var p = jQuery(this);184 var q;185 var n;186 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {187 q = p.data("ojQueryGestures") || {};188 n = {};189 n[o] = false;190 c.extend(true, q, n);191 p.data("ojQueryGestures", q);192 if (c.hasGestures) {193 switch (m) {194 case "orientationchange":195 p.get(0).removeEventListener("orientationchange", a, false);196 break;197 case "shake":198 case "shakefrontback":199 case "shakeleftright":200 case "shakeupdown":201 case "tilt":202 p.get(0).removeEventListener("devicemotion", b, false);203 break;204 case "tap":205 case "swipe":206 case "swipeup":207 case "swiperightup":208 case "swiperight":209 case "swiperightdown":210 case "swipedown":211 case "swipeleftdown":212 case "swipeleft":213 case "swipeleftup":214 p.get(0).removeEventListener("touchstart", h, false);215 p.get(0).removeEventListener("touchmove", g, false);216 p.get(0).removeEventListener("touchend", j, false);217 break;218 case "pinchopen":219 case "pinchclose":220 case "rotatecw":221 case "rotateccw":222 p.get(0).removeEventListener("gesturestart", e, false);223 p.get(0).removeEventListener("gestureend", i, false);224 break;225 case "pinch":226 case "rotate":227 p.get(0).removeEventListener("gesturestart", e, false);228 p.get(0).removeEventListener("gesturechange", f, false);229 break230 }231 } else {232 switch (m) {233 case "tap":234 case "swipe":235 p.unbind("mousedown", h);236 p.unbind("mousemove", g);237 p.unbind("mouseup", j);238 break;239 case "orientationchange":240 case "pinchopen":241 case "pinchclose":242 case "rotatecw":243 case "rotateccw":244 case "pinch":245 case "rotate":246 case "shake":247 case "tilt":248 break249 }250 }251 }252 return false253 }254 }255 });256 function d(k) {257 k.startMove = (k.startMove) ? k.startMove: {258 startX: null,259 startY: null,260 timestamp: null261 };262 var l = new Date().getTime();263 var m;264 var n;265 if (k.touches) {266 n = [{267 lastX: k.deltaX,268 lastY: k.deltaY,269 moved: null,270 startX: k.screenX - k.startMove.screenX,271 startY: k.screenY - k.startMove.screenY272 }];273 m = {274 vector: k.vector || null,275 orientation: window.orientation || null,276 lastX: ((n[0].lastX > 0) ? +1 : ((n[0].lastX < 0) ? -1 : 0)),277 lastY: ((n[0].lastY > 0) ? +1 : ((n[0].lastY < 0) ? -1 : 0)),278 startX: ((n[0].startX > 0) ? +1 : ((n[0].startX < 0) ? -1 : 0)),279 startY: ((n[0].startY > 0) ? +1 : ((n[0].startY < 0) ? -1 : 0))280 };281 n[0].moved = Math.sqrt(Math.pow(Math.abs(n[0].startX), 2) + Math.pow(Math.abs(n[0].startY), 2))282 }283 return {284 type: k.type || null,285 originalEvent: k.event || null,286 delta: n || null,287 direction: m || {288 orientation: window.orientation || null,289 vector: k.vector || null290 },291 duration: (k.duration) ? k.duration: (k.startMove.timestamp) ? l - k.timestamp: null,292 rotation: k.rotation || null,293 scale: k.scale || null,294 description: k.description || [k.type, ":", k.touches, ":", ((n[0].lastX != 0) ? ((n[0].lastX > 0) ? "right": "left") : "steady"), ":", ((n[0].lastY != 0) ? ((n[0].lastY > 0) ? "down": "up") : "steady")].join("")295 }296 }297 function a(l) {298 var k = ["landscape:clockwise:", "portrait:default:", "landscape:counterclockwise:", "portrait:upsidedown:"];299 c(window).triggerHandler("orientationchange", {300 direction: {301 orientation: window.orientation302 },303 description: ["orientationchange:", k[((window.orientation / 90) + 1)], window.orientation].join("")304 })305 }306 function b(r) {307 var k;308 var t = jQuery(window);309 var o = t.data("ojQueryGestures");310 var m = c.jGestures.defaults.thresholdShake;311 var n = o.oDeviceMotionLastDevicePosition || {312 accelerationIncludingGravity: {313 x: 0,314 y: 0,315 z: 0316 },317 shake: {318 eventCount: 0,319 intervalsPassed: 0,320 intervalsFreeze: 0321 },322 shakeleftright: {323 eventCount: 0,324 intervalsPassed: 0,325 intervalsFreeze: 0326 },327 shakefrontback: {328 eventCount: 0,329 intervalsPassed: 0,330 intervalsFreeze: 0331 },332 shakeupdown: {333 eventCount: 0,334 intervalsPassed: 0,335 intervalsFreeze: 0336 }337 };338 var q = {339 accelerationIncludingGravity: {340 x: r.accelerationIncludingGravity.x,341 y: r.accelerationIncludingGravity.y,342 z: r.accelerationIncludingGravity.z343 },344 shake: {345 eventCount: n.shake.eventCount,346 intervalsPassed: n.shake.intervalsPassed,347 intervalsFreeze: n.shake.intervalsFreeze348 },349 shakeleftright: {350 eventCount: n.shakeleftright.eventCount,351 intervalsPassed: n.shakeleftright.intervalsPassed,352 intervalsFreeze: n.shakeleftright.intervalsFreeze353 },354 shakefrontback: {355 eventCount: n.shakefrontback.eventCount,356 intervalsPassed: n.shakefrontback.intervalsPassed,357 intervalsFreeze: n.shakefrontback.intervalsFreeze358 },359 shakeupdown: {360 eventCount: n.shakeupdown.eventCount,361 intervalsPassed: n.shakeupdown.intervalsPassed,362 intervalsFreeze: n.shakeupdown.intervalsFreeze363 }364 };365 var p;366 var s;367 var l;368 for (k in o) {369 switch (k) {370 case "shake":371 case "shakeleftright":372 case "shakefrontback":373 case "shakeupdown":374 p = [];375 s = [];376 p.push(k);377 if (++q[k].intervalsFreeze > m.freezeShakes && q[k].intervalsFreeze < (2 * m.freezeShakes)) {378 break379 }380 q[k].intervalsFreeze = 0;381 q[k].intervalsPassed++;382 if ((k === "shake" || k === "shakeleftright") && (q.accelerationIncludingGravity.x > m.leftright.sensitivity || q.accelerationIncludingGravity.x < ( - 1 * m.leftright.sensitivity))) {383 p.push("leftright");384 p.push("x-axis")385 }386 if ((k === "shake" || k === "shakefrontback") && (q.accelerationIncludingGravity.y > m.frontback.sensitivity || q.accelerationIncludingGravity.y < ( - 1 * m.frontback.sensitivity))) {387 p.push("frontback");388 p.push("y-axis")389 }390 if ((k === "shake" || k === "shakeupdown") && (q.accelerationIncludingGravity.z + 9.81 > m.updown.sensitivity || q.accelerationIncludingGravity.z + 9.81 < ( - 1 * m.updown.sensitivity))) {391 p.push("updown");392 p.push("z-axis")393 }394 if (p.length > 1) {395 if (++q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) < m.freezeShakes) {396 t.triggerHandler(k, d({397 type: k,398 description: p.join(":"),399 event: r,400 duration: q[k].intervalsPassed * 5401 }));402 q[k].eventCount = 0;403 q[k].intervalsPassed = 0;404 q[k].intervalsFreeze = m.freezeShakes + 1405 } else {406 if (q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) > m.freezeShakes) {407 q[k].eventCount = 0;408 q[k].intervalsPassed = 0409 }410 }411 }412 break413 }414 l = {};415 l.oDeviceMotionLastDevicePosition = q;416 t.data("ojQueryGestures", c.extend(true, o, l))417 }418 }419 function h(l) {420 var k = jQuery(l.currentTarget);421 k.triggerHandler(c.jGestures.events.touchstart, l);422 if (c.hasGestures) {423 l.currentTarget.addEventListener("touchmove", g, false);424 l.currentTarget.addEventListener("touchend", j, false)425 } else {426 k.bind("mousemove", g);427 k.bind("mouseup", j)428 }429 var n = k.data("ojQueryGestures");430 var m = (l.touches) ? l.touches[0] : l;431 var o = {};432 o.oLastSwipemove = {433 screenX: m.screenX,434 screenY: m.screenY,435 timestamp: new Date().getTime()436 };437 o.oStartTouch = {438 screenX: m.screenX,439 screenY: m.screenY,440 timestamp: new Date().getTime()441 };442 k.data("ojQueryGestures", c.extend(true, n, o))443 }444 function g(t) {445 var v = jQuery(t.currentTarget);446 var s = v.data("ojQueryGestures");447 var q = !!t.touches;448 var l = (q) ? t.changedTouches[0].screenX: t.screenX;449 var k = (q) ? t.changedTouches[0].screenY: t.screenY;450 var r = s.oLastSwipemove;451 var o = l - r.screenX;452 var n = k - r.screenY;453 var u;454 if ( !! s.oLastSwipemove) {455 u = d({456 type: "swipemove",457 touches: (q) ? t.touches.length: "1",458 screenY: k,459 screenX: l,460 deltaY: n,461 deltaX: o,462 startMove: r,463 event: t,464 timestamp: r.timestamp465 });466 v.triggerHandler(u.type, u)467 }468 var m = {};469 var p = (t.touches) ? t.touches[0] : t;470 m.oLastSwipemove = {471 screenX: p.screenX,472 screenY: p.screenY,473 timestamp: new Date().getTime()474 };475 v.data("ojQueryGestures", c.extend(true, s, m))476 }477 function j(r) {478 var v = jQuery(r.currentTarget);479 var x = !!r.changedTouches;480 var u = (x) ? r.changedTouches.length: "1";481 var p = (x) ? r.changedTouches[0].screenX: r.screenX;482 var o = (x) ? r.changedTouches[0].screenY: r.screenY;483 v.triggerHandler(c.jGestures.events.touchendStart, r);484 if (c.hasGestures) {485 r.currentTarget.removeEventListener("touchmove", g, false);486 r.currentTarget.removeEventListener("touchend", j, false)487 } else {488 v.unbind("mousemove", g);489 v.unbind("mouseup", j)490 }491 var m = v.data("ojQueryGestures");492 var y = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdMove || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdMove) ? true: false;493 var B = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdSwipe || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdSwipe) ? true: false;494 var A;495 var t;496 var n;497 var l;498 var k;499 var q;500 var w = ["zero", "one", "two", "three", "four"];501 var s;502 for (A in m) {503 t = m.oStartTouch;504 n = {};505 p = (x) ? r.changedTouches[0].screenX: r.screenX;506 o = (x) ? r.changedTouches[0].screenY: r.screenY;507 l = p - t.screenX;508 k = o - t.screenY;509 q = d({510 type: "swipe",511 touches: u,512 screenY: o,513 screenX: p,514 deltaY: k,515 deltaX: l,516 startMove: t,517 event: r,518 timestamp: t.timestamp519 });520 s = false;521 switch (A) {522 case "swipeone":523 if (x === false && u == 1 && y === false) {524 break525 }526 if (x === false || (u == 1 && y === true && B === true)) {527 s = true;528 q.type = ["swipe", w[u]].join("");529 v.triggerHandler(q.type, q)530 }531 break;532 case "swipetwo":533 if ((x && u == 2 && y === true && B === true)) {534 s = true;535 q.type = ["swipe", w[u]].join("");536 v.triggerHandler(q.type, q)537 }538 break;539 case "swipethree":540 if ((x && u == 3 && y === true && B === true)) {541 s = true;542 q.type = ["swipe", w[u]].join("");543 v.triggerHandler(q.type, q)544 }545 break;546 case "swipefour":547 if ((x && u == 4 && y === true && B === true)) {548 s = true;549 q.type = ["swipe", w[u]].join("");550 v.triggerHandler(q.type, q)551 }552 break;553 case "swipeup":554 case "swiperightup":555 case "swiperight":556 case "swiperightdown":557 case "swipedown":558 case "swipeleftdown":559 case "swipeleft":560 case "swipeleftup":561 if (x && y === true && B === true) {562 s = true;563 q.type = ["swipe", ((q.delta[0].lastX != 0) ? ((q.delta[0].lastX > 0) ? "right": "left") : ""), ((q.delta[0].lastY != 0) ? ((q.delta[0].lastY > 0) ? "down": "up") : "")].join("");564 v.triggerHandler(q.type, q)565 }566 break;567 case "tapone":568 case "taptwo":569 case "tapthree":570 case "tapfour":571 if ((y !== true && s !== true) && (w[u] == A.slice(3))) {572 q.description = ["tap", w[u]].join("");573 q.type = ["tap", w[u]].join("");574 v.triggerHandler(q.type, q)575 }576 break577 }578 var z = {};579 v.data("ojQueryGestures", c.extend(true, m, z));580 v.data("ojQueryGestures", c.extend(true, m, z))581 }582 v.triggerHandler(c.jGestures.events.touchendProcessed, r)583 }584 function e(l) {585 var k = jQuery(l.currentTarget);586 k.triggerHandler(c.jGestures.events.gesturestart, l);587 var m = k.data("ojQueryGestures");588 var n = {};589 n.oStartTouch = {590 timestamp: new Date().getTime()591 };592 k.data("ojQueryGestures", c.extend(true, m, n))593 }594 function f(l) {595 var k = jQuery(l.currentTarget);596 var p, m, r, o;597 var q = k.data("ojQueryGestures");598 var n;599 for (n in q) {600 switch (n) {601 case "pinch":602 p = l.scale;603 if (((p < 1) && (p % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) || ((p > 1) && (p % 1) > (c.jGestures.defaults.thresholdPinchopen))) {604 m = (p < 1) ? -1 : +1;605 o = d({606 type: "pinch",607 scale: p,608 touches: null,609 startMove: q.oStartTouch,610 event: l,611 timestamp: q.oStartTouch.timestamp,612 vector: m,613 description: ["pinch:", m, ":", ((p < 1) ? "close": "open")].join("")614 });615 k.triggerHandler(o.type, o)616 }617 break;618 case "rotate":619 p = l.rotation;620 if (((p < 1) && ( - 1 * (p) > c.jGestures.defaults.thresholdRotateccw)) || ((p > 1) && (p > c.jGestures.defaults.thresholdRotatecw))) {621 m = (p < 1) ? -1 : +1;622 o = d({623 type: "rotate",624 rotation: p,625 touches: null,626 startMove: q.oStartTouch,627 event: l,628 timestamp: q.oStartTouch.timestamp,629 vector: m,630 description: ["rotate:", m, ":", ((p < 1) ? "counterclockwise": "clockwise")].join("")631 });632 k.triggerHandler(o.type, o)633 }634 break635 }636 }637 }638 function i(l) {639 var k = jQuery(l.currentTarget);640 k.triggerHandler(c.jGestures.events.gestureendStart, l);641 var n;642 var o = k.data("ojQueryGestures");643 var m;644 for (m in o) {645 switch (m) {646 case "pinchclose":647 n = l.scale;648 if ((n < 1) && (n % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) {649 k.triggerHandler("pinchclose", d({650 type: "pinchclose",651 scale: n,652 vector: -1,653 touches: null,654 startMove: o.oStartTouch,655 event: l,656 timestamp: o.oStartTouch.timestamp,657 description: "pinch:-1:close"658 }))659 }660 break;661 case "pinchopen":662 n = l.scale;663 if ((n > 1) && (n % 1) > (c.jGestures.defaults.thresholdPinchopen)) {664 k.triggerHandler("pinchopen", d({665 type: "pinchopen",666 scale: n,667 vector: +1,668 touches: null,669 startMove: o.oStartTouch,670 event: l,671 timestamp: o.oStartTouch.timestamp,672 description: "pinch:+1:open"673 }))674 }675 break;676 case "rotatecw":677 n = l.rotation;678 if ((n > 1) && (n > c.jGestures.defaults.thresholdRotatecw)) {679 k.triggerHandler("rotatecw", d({680 type: "rotatecw",681 rotation: n,682 vector: +1,683 touches: null,684 startMove: o.oStartTouch,685 event: l,686 timestamp: o.oStartTouch.timestamp,687 description: "rotate:+1:clockwise"688 }))689 }690 break;691 case "rotateccw":692 n = l.rotation;693 if ((n < 1) && ( - 1 * (n) > c.jGestures.defaults.thresholdRotateccw)) {694 k.triggerHandler("rotateccw", d({695 type: "rotateccw",696 rotation: n,697 vector: -1,698 touches: null,699 startMove: o.oStartTouch,700 event: l,701 timestamp: o.oStartTouch.timestamp,702 description: "rotate:-1:counterclockwise"703 }))704 }705 break706 }707 }708 k.triggerHandler(c.jGestures.events.gestureendProcessed, l)709 }...
jgestures.min.js
Source:jgestures.min.js
1/**2 * jGestures: a jQuery plugin for gesture events3 * Copyright 2010-2011 Neue Digitale / Razorfish GmbH4 * Copyright 2011-2012, Razorfish GmbH5 * Licensed under the Apache License, Version 2.0 (the "License");6 * you may not use this file except in compliance with the License.7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.08 * Unless required by applicable law or agreed to in writing, software9 * distributed under the License is distributed on an "AS IS" BASIS,10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11 * See the License for the specific language governing permissions and12 * limitations under the License.13 * @copyright Razorfish GmbH14 * @author martin.krause@razorfish.de15 * @version 0.90-shake16 * @requires jQuery JavaScript Library v1.4.2 - http://jquery.com/- Copyright 2010, John Resig- Dual licensed under the MIT or GPL Version 2 licenses. http://jquery.org/license17 */18(function(c) {19 c.jGestures = {};20 c.jGestures.defaults = {};21 c.jGestures.defaults.thresholdShake = { requiredShakes: 10, freezeShakes: 100, frontback: { sensitivity: 10 }, leftright: { sensitivity: 10 }, updown: { sensitivity: 10 } };22 c.jGestures.defaults.thresholdPinchopen = 0.05;23 c.jGestures.defaults.thresholdPinchmove = 0.05;24 c.jGestures.defaults.thresholdPinch = 0.05;25 c.jGestures.defaults.thresholdPinchclose = 0.05;26 c.jGestures.defaults.thresholdRotatecw = 5;27 c.jGestures.defaults.thresholdRotateccw = 5;28 c.jGestures.defaults.thresholdMove = 20;29 c.jGestures.defaults.thresholdSwipe = 100;30 c.jGestures.data = {};31 c.jGestures.data.capableDevicesInUserAgentString = ["iPad", "iPhone", "iPod", "Mobile Safari"];32 c.jGestures.data.hasGestures = (function() { var k; for (k = 0; k < c.jGestures.data.capableDevicesInUserAgentString.length; k++) { if (navigator.userAgent.indexOf(c.jGestures.data.capableDevicesInUserAgentString[k]) !== -1) { return true } } return false })();33 c.hasGestures = c.jGestures.data.hasGestures;34 c.jGestures.events = { touchstart: "jGestures.touchstart", touchendStart: "jGestures.touchend;start", touchendProcessed: "jGestures.touchend;processed", gesturestart: "jGestures.gesturestart", gestureendStart: "jGestures.gestureend;start", gestureendProcessed: "jGestures.gestureend;processed" };35 jQuery.each({ orientationchange_orientationchange01: "orientationchange", gestureend_pinchopen01: "pinchopen", gestureend_pinchclose01: "pinchclose", gestureend_rotatecw01: "rotatecw", gestureend_rotateccw01: "rotateccw", gesturechange_pinch01: "pinch", gesturechange_rotate01: "rotate", touchstart_swipe13: "swipemove", touchstart_swipe01: "swipeone", touchstart_swipe02: "swipetwo", touchstart_swipe03: "swipethree", touchstart_swipe04: "swipefour", touchstart_swipe05: "swipeup", touchstart_swipe06: "swiperightup", touchstart_swipe07: "swiperight", touchstart_swipe08: "swiperightdown", touchstart_swipe09: "swipedown", touchstart_swipe10: "swipeleftdown", touchstart_swipe11: "swipeleft", touchstart_swipe12: "swipeleftup", touchstart_tap01: "tapone", touchstart_tap02: "taptwo", touchstart_tap03: "tapthree", touchstart_tap04: "tapfour", devicemotion_shake01: "shake", devicemotion_shake02: "shakefrontback", devicemotion_shake03: "shakeleftright", devicemotion_shake04: "shakeupdown" }, function(l, k) {36 jQuery.event.special[k] = {37 setup: function() {38 var r = l.split("_");39 var o = r[0];40 var m = r[1].slice(0, r[1].length - 2);41 var p = jQuery(this);42 var q;43 var n;44 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {45 q = p.data("ojQueryGestures") || {};46 n = {};47 n[o] = true;48 c.extend(true, q, n);49 p.data("ojQueryGestures", q);50 if (c.hasGestures) {51 switch (m) {52 case "orientationchange":53 p.get(0).addEventListener("orientationchange", a, false);54 break;55 case "shake":56 case "shakefrontback":57 case "shakeleftright":58 case "shakeupdown":59 case "tilt":60 p.get(0).addEventListener("devicemotion", b, false);61 break;62 case "tap":63 case "swipe":64 case "swipeup":65 case "swiperightup":66 case "swiperight":67 case "swiperightdown":68 case "swipedown":69 case "swipeleftdown":70 case "swipeleft":71 p.get(0).addEventListener("touchstart", h, false);72 break;73 case "pinchopen":74 case "pinchclose":75 case "rotatecw":76 case "rotateccw":77 p.get(0).addEventListener("gesturestart", e, false);78 p.get(0).addEventListener("gestureend", i, false);79 break;80 case "pinch":81 case "rotate":82 p.get(0).addEventListener("gesturestart", e, false);83 p.get(0).addEventListener("gesturechange", f, false);84 break85 }86 } else {87 switch (m) {88 case "tap":89 case "swipe":90 p.bind("mousedown", h);91 break;92 case "orientationchange":93 case "pinchopen":94 case "pinchclose":95 case "rotatecw":96 case "rotateccw":97 case "pinch":98 case "rotate":99 case "shake":100 case "tilt":101 break102 }103 }104 }105 return false106 },107 add: function(n) {108 var m = jQuery(this);109 var o = m.data("ojQueryGestures");110 o[n.type] = { originalType: n.type };111 return false112 },113 remove: function(n) {114 var m = jQuery(this);115 var o = m.data("ojQueryGestures");116 o[n.type] = false;117 m.data("ojQueryGestures", o);118 return false119 },120 teardown: function() {121 var r = l.split("_");122 var o = r[0];123 var m = r[1].slice(0, r[1].length - 2);124 var p = jQuery(this);125 var q;126 var n;127 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {128 q = p.data("ojQueryGestures") || {};129 n = {};130 n[o] = false;131 c.extend(true, q, n);132 p.data("ojQueryGestures", q);133 if (c.hasGestures) {134 switch (m) {135 case "orientationchange":136 p.get(0).removeEventListener("orientationchange", a, false);137 break;138 case "shake":139 case "shakefrontback":140 case "shakeleftright":141 case "shakeupdown":142 case "tilt":143 p.get(0).removeEventListener("devicemotion", b, false);144 break;145 case "tap":146 case "swipe":147 case "swipeup":148 case "swiperightup":149 case "swiperight":150 case "swiperightdown":151 case "swipedown":152 case "swipeleftdown":153 case "swipeleft":154 case "swipeleftup":155 p.get(0).removeEventListener("touchstart", h, false);156 p.get(0).removeEventListener("touchmove", g, false);157 p.get(0).removeEventListener("touchend", j, false);158 break;159 case "pinchopen":160 case "pinchclose":161 case "rotatecw":162 case "rotateccw":163 p.get(0).removeEventListener("gesturestart", e, false);164 p.get(0).removeEventListener("gestureend", i, false);165 break;166 case "pinch":167 case "rotate":168 p.get(0).removeEventListener("gesturestart", e, false);169 p.get(0).removeEventListener("gesturechange", f, false);170 break171 }172 } else {173 switch (m) {174 case "tap":175 case "swipe":176 p.unbind("mousedown", h);177 p.unbind("mousemove", g);178 p.unbind("mouseup", j);179 break;180 case "orientationchange":181 case "pinchopen":182 case "pinchclose":183 case "rotatecw":184 case "rotateccw":185 case "pinch":186 case "rotate":187 case "shake":188 case "tilt":189 break190 }191 }192 }193 return false194 }195 }196 });197 function d(k) {198 k.startMove = (k.startMove) ? k.startMove : { startX: null, startY: null, timestamp: null };199 var l = new Date().getTime();200 var m;201 var n;202 if (k.touches) {203 n = [{ lastX: k.deltaX, lastY: k.deltaY, moved: null, startX: k.screenX - k.startMove.screenX, startY: k.screenY - k.startMove.screenY }];204 m = { vector: k.vector || null, orientation: window.orientation || null, lastX: ((n[0].lastX > 0) ? +1 : ((n[0].lastX < 0) ? -1 : 0)), lastY: ((n[0].lastY > 0) ? +1 : ((n[0].lastY < 0) ? -1 : 0)), startX: ((n[0].startX > 0) ? +1 : ((n[0].startX < 0) ? -1 : 0)), startY: ((n[0].startY > 0) ? +1 : ((n[0].startY < 0) ? -1 : 0)) };205 n[0].moved = Math.sqrt(Math.pow(Math.abs(n[0].startX), 2) + Math.pow(Math.abs(n[0].startY), 2))206 }207 return { type: k.type || null, originalEvent: k.event || null, delta: n || null, direction: m || { orientation: window.orientation || null, vector: k.vector || null }, duration: (k.duration) ? k.duration : (k.startMove.timestamp) ? l - k.timestamp : null, rotation: k.rotation || null, scale: k.scale || null, description: k.description || [k.type, ":", k.touches, ":", ((n[0].lastX != 0) ? ((n[0].lastX > 0) ? "right" : "left") : "steady"), ":", ((n[0].lastY != 0) ? ((n[0].lastY > 0) ? "down" : "up") : "steady")].join("") }208 }209 function a(l) {210 var k = ["landscape:clockwise:", "portrait:default:", "landscape:counterclockwise:", "portrait:upsidedown:"];211 c(window).triggerHandler("orientationchange", { direction: { orientation: window.orientation }, description: ["orientationchange:", k[((window.orientation / 90) + 1)], window.orientation].join("") })212 }213 function b(r) {214 var k;215 var t = jQuery(window);216 var o = t.data("ojQueryGestures");217 var m = c.jGestures.defaults.thresholdShake;218 var n = o.oDeviceMotionLastDevicePosition || { accelerationIncludingGravity: { x: 0, y: 0, z: 0 }, shake: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 }, shakeleftright: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 }, shakefrontback: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 }, shakeupdown: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 } };219 var q = { accelerationIncludingGravity: { x: r.accelerationIncludingGravity.x, y: r.accelerationIncludingGravity.y, z: r.accelerationIncludingGravity.z }, shake: { eventCount: n.shake.eventCount, intervalsPassed: n.shake.intervalsPassed, intervalsFreeze: n.shake.intervalsFreeze }, shakeleftright: { eventCount: n.shakeleftright.eventCount, intervalsPassed: n.shakeleftright.intervalsPassed, intervalsFreeze: n.shakeleftright.intervalsFreeze }, shakefrontback: { eventCount: n.shakefrontback.eventCount, intervalsPassed: n.shakefrontback.intervalsPassed, intervalsFreeze: n.shakefrontback.intervalsFreeze }, shakeupdown: { eventCount: n.shakeupdown.eventCount, intervalsPassed: n.shakeupdown.intervalsPassed, intervalsFreeze: n.shakeupdown.intervalsFreeze } };220 var p;221 var s;222 var l;223 for (k in o) {224 switch (k) {225 case "shake":226 case "shakeleftright":227 case "shakefrontback":228 case "shakeupdown":229 p = [];230 s = [];231 p.push(k);232 if (++q[k].intervalsFreeze > m.freezeShakes && q[k].intervalsFreeze < (2 * m.freezeShakes)) { break }233 q[k].intervalsFreeze = 0;234 q[k].intervalsPassed++;235 if ((k === "shake" || k === "shakeleftright") && (q.accelerationIncludingGravity.x > m.leftright.sensitivity || q.accelerationIncludingGravity.x < (-1 * m.leftright.sensitivity))) {236 p.push("leftright");237 p.push("x-axis")238 }239 if ((k === "shake" || k === "shakefrontback") && (q.accelerationIncludingGravity.y > m.frontback.sensitivity || q.accelerationIncludingGravity.y < (-1 * m.frontback.sensitivity))) {240 p.push("frontback");241 p.push("y-axis")242 }243 if ((k === "shake" || k === "shakeupdown") && (q.accelerationIncludingGravity.z + 9.81 > m.updown.sensitivity || q.accelerationIncludingGravity.z + 9.81 < (-1 * m.updown.sensitivity))) {244 p.push("updown");245 p.push("z-axis")246 }247 if (p.length > 1) {248 if (++q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) < m.freezeShakes) {249 t.triggerHandler(k, d({ type: k, description: p.join(":"), event: r, duration: q[k].intervalsPassed * 5 }));250 q[k].eventCount = 0;251 q[k].intervalsPassed = 0;252 q[k].intervalsFreeze = m.freezeShakes + 1253 } else {254 if (q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) > m.freezeShakes) {255 q[k].eventCount = 0;256 q[k].intervalsPassed = 0257 }258 }259 }260 break261 }262 l = {};263 l.oDeviceMotionLastDevicePosition = q;264 t.data("ojQueryGestures", c.extend(true, o, l))265 }266 }267 function h(l) {268 var k = jQuery(l.currentTarget);269 k.triggerHandler(c.jGestures.events.touchstart, l);270 if (c.hasGestures) {271 l.currentTarget.addEventListener("touchmove", g, false);272 l.currentTarget.addEventListener("touchend", j, false)273 } else {274 k.bind("mousemove", g);275 k.bind("mouseup", j)276 }277 var n = k.data("ojQueryGestures");278 var m = (l.touches) ? l.touches[0] : l;279 var o = {};280 o.oLastSwipemove = { screenX: m.screenX, screenY: m.screenY, timestamp: new Date().getTime() };281 o.oStartTouch = { screenX: m.screenX, screenY: m.screenY, timestamp: new Date().getTime() };282 k.data("ojQueryGestures", c.extend(true, n, o))283 }284 function g(t) {285 var v = jQuery(t.currentTarget);286 var s = v.data("ojQueryGestures");287 var q = !!t.touches;288 var l = (q) ? t.changedTouches[0].screenX : t.screenX;289 var k = (q) ? t.changedTouches[0].screenY : t.screenY;290 var r = s.oLastSwipemove;291 var o = l - r.screenX;292 var n = k - r.screenY;293 var u;294 if (!!s.oLastSwipemove) {295 u = d({ type: "swipemove", touches: (q) ? t.touches.length : "1", screenY: k, screenX: l, deltaY: n, deltaX: o, startMove: r, event: t, timestamp: r.timestamp });296 v.triggerHandler(u.type, u)297 }298 var m = {};299 var p = (t.touches) ? t.touches[0] : t;300 m.oLastSwipemove = { screenX: p.screenX, screenY: p.screenY, timestamp: new Date().getTime() };301 v.data("ojQueryGestures", c.extend(true, s, m))302 }303 function j(r) {304 var v = jQuery(r.currentTarget);305 var x = !!r.changedTouches;306 var u = (x) ? r.changedTouches.length : "1";307 var p = (x) ? r.changedTouches[0].screenX : r.screenX;308 var o = (x) ? r.changedTouches[0].screenY : r.screenY;309 v.triggerHandler(c.jGestures.events.touchendStart, r);310 if (c.hasGestures) {311 r.currentTarget.removeEventListener("touchmove", g, false);312 r.currentTarget.removeEventListener("touchend", j, false)313 } else {314 v.unbind("mousemove", g);315 v.unbind("mouseup", j)316 }317 var m = v.data("ojQueryGestures");318 var y = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdMove || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdMove) ? true : false;319 var B = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdSwipe || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdSwipe) ? true : false;320 var A;321 var t;322 var n;323 var l;324 var k;325 var q;326 var w = ["zero", "one", "two", "three", "four"];327 var s;328 for (A in m) {329 t = m.oStartTouch;330 n = {};331 p = (x) ? r.changedTouches[0].screenX : r.screenX;332 o = (x) ? r.changedTouches[0].screenY : r.screenY;333 l = p - t.screenX;334 k = o - t.screenY;335 q = d({ type: "swipe", touches: u, screenY: o, screenX: p, deltaY: k, deltaX: l, startMove: t, event: r, timestamp: t.timestamp });336 s = false;337 switch (A) {338 case "swipeone":339 if (x === false && u == 1 && y === false) { break }340 if (x === false || (u == 1 && y === true && B === true)) {341 s = true;342 q.type = ["swipe", w[u]].join("");343 v.triggerHandler(q.type, q)344 }345 break;346 case "swipetwo":347 if ((x && u == 2 && y === true && B === true)) {348 s = true;349 q.type = ["swipe", w[u]].join("");350 v.triggerHandler(q.type, q)351 }352 break;353 case "swipethree":354 if ((x && u == 3 && y === true && B === true)) {355 s = true;356 q.type = ["swipe", w[u]].join("");357 v.triggerHandler(q.type, q)358 }359 break;360 case "swipefour":361 if ((x && u == 4 && y === true && B === true)) {362 s = true;363 q.type = ["swipe", w[u]].join("");364 v.triggerHandler(q.type, q)365 }366 break;367 case "swipeup":368 case "swiperightup":369 case "swiperight":370 case "swiperightdown":371 case "swipedown":372 case "swipeleftdown":373 case "swipeleft":374 case "swipeleftup":375 if (x && y === true && B === true) {376 s = true;377 q.type = ["swipe", ((q.delta[0].lastX != 0) ? ((q.delta[0].lastX > 0) ? "right" : "left") : ""), ((q.delta[0].lastY != 0) ? ((q.delta[0].lastY > 0) ? "down" : "up") : "")].join("");378 v.triggerHandler(q.type, q)379 }380 break;381 case "tapone":382 case "taptwo":383 case "tapthree":384 case "tapfour":385 if ((y !== true && s !== true) && (w[u] == A.slice(3))) {386 q.description = ["tap", w[u]].join("");387 q.type = ["tap", w[u]].join("");388 v.triggerHandler(q.type, q)389 }390 break391 }392 var z = {};393 v.data("ojQueryGestures", c.extend(true, m, z));394 v.data("ojQueryGestures", c.extend(true, m, z))395 }396 v.triggerHandler(c.jGestures.events.touchendProcessed, r)397 }398 function e(l) {399 var k = jQuery(l.currentTarget);400 k.triggerHandler(c.jGestures.events.gesturestart, l);401 var m = k.data("ojQueryGestures");402 var n = {};403 n.oStartTouch = { timestamp: new Date().getTime() };404 k.data("ojQueryGestures", c.extend(true, m, n))405 }406 function f(l) {407 var k = jQuery(l.currentTarget);408 var p, m, r, o;409 var q = k.data("ojQueryGestures");410 var n;411 for (n in q) {412 switch (n) {413 case "pinch":414 p = l.scale;415 if (((p < 1) && (p % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) || ((p > 1) && (p % 1) > (c.jGestures.defaults.thresholdPinchopen))) {416 m = (p < 1) ? -1 : +1;417 o = d({ type: "pinch", scale: p, touches: null, startMove: q.oStartTouch, event: l, timestamp: q.oStartTouch.timestamp, vector: m, description: ["pinch:", m, ":", ((p < 1) ? "close" : "open")].join("") });418 k.triggerHandler(o.type, o)419 }420 break;421 case "rotate":422 p = l.rotation;423 if (((p < 1) && (-1 * (p) > c.jGestures.defaults.thresholdRotateccw)) || ((p > 1) && (p > c.jGestures.defaults.thresholdRotatecw))) {424 m = (p < 1) ? -1 : +1;425 o = d({ type: "rotate", rotation: p, touches: null, startMove: q.oStartTouch, event: l, timestamp: q.oStartTouch.timestamp, vector: m, description: ["rotate:", m, ":", ((p < 1) ? "counterclockwise" : "clockwise")].join("") });426 k.triggerHandler(o.type, o)427 }428 break429 }430 }431 }432 function i(l) {433 var k = jQuery(l.currentTarget);434 k.triggerHandler(c.jGestures.events.gestureendStart, l);435 var n;436 var o = k.data("ojQueryGestures");437 var m;438 for (m in o) {439 switch (m) {440 case "pinchclose":441 n = l.scale;442 if ((n < 1) && (n % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) { k.triggerHandler("pinchclose", d({ type: "pinchclose", scale: n, vector: -1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "pinch:-1:close" })) }443 break;444 case "pinchopen":445 n = l.scale;446 if ((n > 1) && (n % 1) > (c.jGestures.defaults.thresholdPinchopen)) { k.triggerHandler("pinchopen", d({ type: "pinchopen", scale: n, vector: +1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "pinch:+1:open" })) }447 break;448 case "rotatecw":449 n = l.rotation;450 if ((n > 1) && (n > c.jGestures.defaults.thresholdRotatecw)) { k.triggerHandler("rotatecw", d({ type: "rotatecw", rotation: n, vector: +1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "rotate:+1:clockwise" })) }451 break;452 case "rotateccw":453 n = l.rotation;454 if ((n < 1) && (-1 * (n) > c.jGestures.defaults.thresholdRotateccw)) { k.triggerHandler("rotateccw", d({ type: "rotateccw", rotation: n, vector: -1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "rotate:-1:counterclockwise" })) }455 break456 }457 }458 k.triggerHandler(c.jGestures.events.gestureendProcessed, l)459 }...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!