How to use pinchClose method in fMBT

Best Python code snippet using fMBT_python

jquery.gestures.js

Source:jquery.gestures.js Github

copy

Full Screen

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);...

Full Screen

Full Screen

mobile.js

Source:mobile.js Github

copy

Full Screen

1/*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 */2/**3 * jGestures: a jQuery plugin for gesture events4 * Copyright 2010-2011 Neue Digitale / Razorfish GmbH5 * Copyright 2011-2012, Razorfish GmbH6 *7 * Licensed under the Apache License, Version 2.0 (the "License");8 * you may not use this file except in compliance with the License.9 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.010 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 *16 * @fileOverview17 * Razorfish GmbH javascript library: add touch events such as 'pinch',18 * 'rotate', 'swipe', 'tap' and 'orientationchange' on capable user agents.19 * For incapable devices there's a basic event substitution: a "tapone" event20 * can be triggered by "clicking", a "swipeone" by performing a swipe-ish21 * gesture using the mouse (buttondown - mousemove - buttonup).22 *23 * This is still a beta version, bugfixes and improvements appreciated.24 *25 * @author martin.krause@razorfish.de26 * @version 0.90-shake27 *28 * @requires29 * jQuery JavaScript Library v1.4.2 - http://jquery.com/30 * Copyright 2010, John Resig31 * Dual licensed under the MIT or GPL Version 2 licenses.32 * http://jquery.org/license33 *34 * @example jQuery('#swipe').bind('swipeone',eventHandler);35 *36 * Notification on native events:37 * On every native touchstart, touchend, gesturestart and gestureend-event,38 * jgestures triggers a corresponding custom event39 * ('jGestures.touchstart', 'jGestures.touchend;start', 'jGestures.touchend;processed',40 * 'jGestures.gesturestart', 'jGestures.gestureend;start', 'jGestures.gestureend;processed') on the event-element.41 * The eventhandler's second argument represents the original touch event (yes: including all touchpoints).42 * Use this if you need very detailed control e.g. kinetic scrolling or implementing additional gestures.43 *44 * Every jGesture-eventhandler receives a custom object as second argument45 * containing the original event (originalEvent property) and processed46 * information (such as delta values and timesptamp).47 * Example:{48 * type: eventtype e.g. "swipe","pinch",49 * originalEvent: {DOM-Event},50 * // default: just one entry on the delta-array - the first touchpoint51 * // the first touchpoint is the reference point for every gesture,52 * // because moving touchpoints in various directions would result in53 * // a gesture.54 * // delta and direction details are just provided for touch not for gesture / motion events55 * delta : [56 * {57 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)58 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)59 * moved: {Number}, // distance: relative to the original touchpoint60 * startX: {Number} , // relative to the original touchpoint61 * startY: {Number} ,// relative to the original touchpoint62 * } ],63 * // based on the first touchpoint64 * direction : { // relative to the last touchevent (e.g. touchmove!)65 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)66 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)67 * lastX : {Number}, // -1,0,+1 || null (orientationchange) // relative to the last touchevent (e.g. touchmove!)68 * lastY : {Number}, // -1,0,+1 || null (orientationchange)// relative to the last touchevent (e.g. touchmove!)69 * startX: {Number} , // relative to the original touchpoint70 * startY: {Number} ,// relative to the original touchpoint71 * },72 * rotation: {Number} || null, // gestureonly: amount of rotation relative to the current position NOT the original73 * scale: {Number} || null, // gestureonly: amount of scaling relative to the current position NOT the original74 * duration: {Number}, // ms: relative to the original touchpoint75 * 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 touchpoint76 * };77 *78 * Available jGesture-events can be grouped into:79 *80 *81 * Device events:82 * The jGesture-Events in this group are triggered by the device.83 *84 * @event 'orientationchange'85 * The device is turned clockwise or counterclockwise. This event is triggered86 * by the device and might use an internal gyroscope.87 * obj.description:88 * orientationchange:landscape:clockwise:-9089 * orientationchange:portrait:default:090 * orientationchange:landscape:counterclockwise|portrait:9091 * orientationchange:portrait:upsidedown:18092 *93 *94 * Move events:95 * The jGesture-Events in this group are triggered during the touch/gesture96 * execution whenever a touchpoint changes.97 * In contrast to touchend/gestureend-events which are triggered after98 * the touch/gesture has completed.99 *100 * @event 'pinch'101 * Is triggered during a pinch gesture (two fingers moving away from or102 * towards each other).103 * obj.description:104 * pinch:-1:close105 * pinch:+1:open106 *107 * @event 'rotate'108 * Is triggered during a rotation gesture (two fingers rotating clockwise109 * or counterclockwise).110 * obj.description:111 * rotate:-1:counterclockwise112 * rotate:+1:+clockwise113 *114 * @event 'swipemove'115 * Is triggered during a swipe move gesture (finger(s) being moved around116 * the device, e.g. dragging)117 * obj.description:118 * swipemove:1:left:down119 * swipemove:1:left:up120 * swipemove:1:left:steady121 * swipemove:1:right:down122 * swipemove:1:right:up123 * swipemove:1:right:steady124 * swipemove:2:left:down125 * swipemove:2:left:up126 * swipemove:2:left:steady127 * swipemove:2:right:down128 * swipemove:2:right:up129 * swipemove:2:right:steady130 * swipemove:2:left:down131 * swipemove:3:left:up132 * swipemove:3:left:steady133 * swipemove:3:right:down134 * swipemove:3:right:up135 * swipemove:3:right:steady136 * swipemove:3:left:down137 * swipemove:4:left:up138 * swipemove:4:left:steady139 * swipemove:4:right:down140 * swipemove:4:right:up141 * swipemove:4:right:steady142 *143 *144 * Toucheend events:145 * The jGesture-Events in this group are triggered after the touch/gesture146 * has completed.147 * In contrast to touchmove-events which are triggered during the touch/gesture148 * execution whenever a touchpoint changes.149 *150 * @event 'swipeone'151 * Is triggered after a swipe move gesture with one touchpoint (one finger152 * was moved around the device)153 * obj.description:154 * swipeone:1:left:down155 * swipeone:1:left:up156 * swipeone:1:left:steady157 * swipeone:1:right:down158 * swipeone:1:right:up159 * swipeone:1:right:steady160 *161 * @event 'swipetwo'162 * Is triggered after a swipe move gesture with two touchpoints (two fingers163 * were moved around the device)164 * obj.description:165 * swipetwo:2:left:down166 * swipetwo:2:left:up167 * swipetwo:2:left:steady168 * swipetwo:2:right:down169 * swipetwo:2:right:up170 * swipetwo:2:right:steady171 *172 * @event 'swipethree'173 * Is triggered after a swipe move gesture with three touchpoints (three174 * fingers were moved around the device)175 * obj.description:176 * swipethree:3:left:down177 * swipethree:3:left:up178 * swipethree:3:left:steady179 * swipethree:3:right:down180 * swipethree:3:right:up181 * swipethree:3:right:steady182 *183 * @event 'swipefour'184 * Is triggered after a swipe move gesture with four touchpoints (four185 * fingers were moved around the device)186 * obj.description:187 * swipefour:4:left:down188 * swipefour:4:left:up189 * swipefour:4:left:steady190 * swipefour:4:right:down191 * swipefour:4:right:up192 * swipefour:4:right:steady193 *194 *195 * @event 'swipeup'196 * Is triggered after an strict upwards swipe move gesture197 * obj.description:198 * swipe:1:steady:up199 * swipe:2:steady:up200 * swipe:3:steady:up201 * swipe:4:steady:up202 *203 * @event 'swiperightup'204 * Is triggered after a rightwards and upwards swipe move gesture205 * obj.description:206 * swipe:1:right:up207 * swipe:2:right:up208 * swipe:3:right:up209 * swipe:4:right:up210 *211 * @event 'swiperight'212 * Is triggered after a strict rightwards swipe move gesture213 * obj.description:214 * swipe:1:right:steady215 * swipe:2:right:steady216 * swipe:3:right:steady217 * swipe:4:right:steady218 *219 * @event 'swiperightdown'220 * Is triggered after a rightwards and downwards swipe move gesture221 * obj.description:222 * swipe:1:right:down223 * swipe:2:right:down224 * swipe:3:right:down225 * swipe:4:right:down226 *227 * @event 'swipedown'228 * Is triggered after a strict downwards swipe move gesture229 * obj.description:230 * swipe:1:steady:down231 * swipe:2:steady:down232 * swipe:3:steady:down233 * swipe:4:steady:down234 *235 * @event 'swipeleftdown'236 * Is triggered after a leftwards and downwards swipe move gesture237 * obj.description:238 * swipe:1:left:down239 * swipe:2:left:down240 * swipe:3:left:down241 * swipe:4:left:down242 *243 * @event 'swipeleft'244 * Is triggered after a strict leftwards swipe move gesture245 * obj.description:246 * swipe:1:left:steady247 * swipe:2:left:steady248 * swipe:3:left:steady249 * swipe:4:left:steady250 *251 * @event 'swipeleftup'252 * Is triggered after a leftwards and upwards swipe move gesture253 * obj.description:254 * swipe:1:left:up255 * swipe:2:left:up256 * swipe:3:left:up257 * swipe:4:left:up258 *259 * @event 'tapone'260 * Is triggered after a single (one finger) tap gesture261 * obj.description:262 * tapone263 *264 * @event 'taptwo'265 * Is triggered after a double (two finger) tap gesture266 * obj.description:267 * taptwo268 * *269 * @event 'tapthree'270 * Is triggered after a tripple (three finger) tap gesture271 * obj.description:272 * tapthree273 *274 *275 * Gestureend events:276 * A gesture is an interpretation of different touchpoints.277 * The jGesture-Events in this group are triggered when a gesture has finished278 * and the touchpoints are removed from the device.279 *280 * @event 'pinchopen'281 * Is triggered when a pinchopen gesture (two fingers moving away from each282 * other) occured and the touchpoints (fingers) are removed the device.283 * obj.description:284 * pinch:+1:open285 *286 * @event 'pinchclose'287 * Is triggered when a pinchclose gesture (two fingers moving towards each288 * other) occured and the touchpoints (fingers) are removed the device.289 * obj.description:290 * pinch:-1:close291 *292 * @event 'rotatecw'293 * Is triggered when a clockwise rotation gesture (two fingers rotating294 * clockwise) occured and the touchpoints (fingers) are removed the device.295 * obj.description:296 * rotate:+1:+clockwise297 *298 * @event 'rotateccw'299 * Is triggered when a counterclockwise rotation gesture (two fingers300 * rotating counterclockwise) occured and the touchpoints (fingers) are301 * removed the device.302 * obj.description:303 * rotate:-1:+counterclockwise304 *305 *306 * Motion events:307 * A "motion event" is an interpretation of changes in space, e.g. a "shaking motion"308 * consists of a specified number of acceleration changes in a given interval.309 * For understanding "directions", place your mobile device on a table with the bottom310 * (home button) close to you:311 * - x-axis: horizontal left / right312 * - y-axis: horizontal front / back (through the home button)313 * - z-axis: vertical through your device314 *315 * Note: Devicemotion / deviceorientation don't send custom event (such as: jGestures.touchstart).316 * Note: Devicemotion should be bound on the "window-element" - because the whole device moves317 *318 * @event 'shake'319 * Is triggered when a shaking motion is detected320 * obj.description:321 * shake:leftright:x-axisfrontback:y-axis:updown:z-axis322 *323 * @event 'shakefrontback'324 * Is triggered when a shaking motion is detected and the gesture can be interpreted as a mainly front-back movement.325 * obj.description:326 * shakefrontback:shakefrontback:y-axis327 *328 * @event 'shakeleftright'329 * Is triggered when a shaking motion is detected and the gesture can be interpreted as a mainly left-right movement.330 * Additional major movements are mentioned in the obj.description.331 * obj.description:332 * shakeleftright:leftright:x-axis333 *334 * @event 'shakeupdown'335 * Is triggered when a shaking motion is detected and the gesture can be interpreted as a mainly up-down movement.336 * Additional major movements are mentioned in the obj.description.337 * obj.description:338 * shake:shakeupdown:updown:z-axis339 *340 * @example341 * .bind( eventType, [ eventData ], handler(eventObject) )342 * jQuery('body').bind('tapone',function(){alert(arguments[1].description);})343 *344 */345 (function($) {346 /**347 * General thresholds.348 */349 // @TODO: move to $...defaults350 // @TODO: shake to defaults freeze etc351 // change of x deg in y ms352 $.jGestures = {};353 $.jGestures.defaults = {};354 $.jGestures.defaults.thresholdShake = {355 requiredShakes : 10,356 freezeShakes: 100,357 frontback : {358 sensitivity: 10359 },360 leftright : {361 sensitivity: 10362 },363 updown : {364 sensitivity: 10365 }366 };367 $.jGestures.defaults.thresholdPinchopen = 0.05;368 $.jGestures.defaults.thresholdPinchmove = 0.05;369 $.jGestures.defaults.thresholdPinch = 0.05;370 $.jGestures.defaults.thresholdPinchclose = 0.05;371 $.jGestures.defaults.thresholdRotatecw = 5; //deg372 $.jGestures.defaults.thresholdRotateccw = 5; // deg373 // a tap becomes a swipe if x/y values changes are above this threshold374 $.jGestures.defaults.thresholdMove = 20;375 $.jGestures.defaults.thresholdSwipe = 100;376 // get capable user agents377 $.jGestures.data = {};378 $.jGestures.data.capableDevicesInUserAgentString = ['iPad','iPhone','iPod','Mobile Safari']; // basic functionality such as swipe, pinch, rotate, tap should work on every mobile safari, e.g. GalaxyTab379 $.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; } )();380 $.hasGestures = $.jGestures.data.hasGestures;381 $.jGestures.events = {382 touchstart : 'jGestures.touchstart',383 touchendStart: 'jGestures.touchend;start',384 touchendProcessed: 'jGestures.touchend;processed',385 gesturestart: 'jGestures.gesturestart',386 gestureendStart: 'jGestures.gestureend;start',387 gestureendProcessed: 'jGestures.gestureend;processed'388 };389 jQuery390 .each({391 // "first domevent necessary"_"touch event+counter" : "exposed as"392 // event: orientationchange393 orientationchange_orientationchange01: "orientationchange",394 // event: gestures395 gestureend_pinchopen01: "pinchopen",396 gestureend_pinchclose01: "pinchclose",397 gestureend_rotatecw01 : 'rotatecw',398 gestureend_rotateccw01 : 'rotateccw',399 // move events400 gesturechange_pinch01: 'pinch',401 gesturechange_rotate01: 'rotate',402 touchstart_swipe13: 'swipemove',403 // event: touches404 touchstart_swipe01: "swipeone",405 touchstart_swipe02: "swipetwo",406 touchstart_swipe03: "swipethree",407 touchstart_swipe04: "swipefour",408 touchstart_swipe05: 'swipeup',409 touchstart_swipe06: 'swiperightup',410 touchstart_swipe07: 'swiperight',411 touchstart_swipe08: 'swiperightdown',412 touchstart_swipe09: 'swipedown',413 touchstart_swipe10: 'swipeleftdown',414 touchstart_swipe11: 'swipeleft',415 touchstart_swipe12: 'swipeleftup',416 touchstart_tap01: 'tapone',417 touchstart_tap02: 'taptwo',418 touchstart_tap03: 'tapthree',419 touchstart_tap04: 'tapfour',420 devicemotion_shake01: 'shake',421 devicemotion_shake02: 'shakefrontback',422 devicemotion_shake03: 'shakeleftright',423 devicemotion_shake04: 'shakeupdown'424 },425 /**426 * Add gesture events inside the jQuery.event.special namespace427 */428 function( sInternal_, sPublicFN_ ) {429 // add as funciton to jQuery.event.special.sPublicFN_430 jQuery.event.special[ sPublicFN_ ] = {431 /**432 * When the first event handler is bound, jQuery executes the setup function.433 * This plugin just uses one eventhandler per element, regardless of the number of bound events.434 * All Events are stored internally as properties on the dom-element using the $.data api.435 * The setup-function adds the eventlistener, acting as a proxy function for the internal events.436 * $.data.ojQueryGestures[_sDOMEvent ('tap') ] = {Boolean}437 * @return {Void}438 */439 setup: function () {440 // split the arguments to necessary controll arguements441 var _aSplit = sInternal_.split('_');442 var _sDOMEvent = _aSplit[0]; //443 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour444 var _sGestureEvent = _aSplit[1].slice(0,_aSplit[1].length-2);445 var _$element = jQuery(this);446 var _oDatajQueryGestures ;447 var oObj;448 // bind the event handler on the first $.bind() for a gestureend-event, set marker449 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {450 // setup pseudo event451 _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};452 oObj = {};453 // marker for: domEvent being set on this element454 // e.g.: $.data.oGestureInternals['touchstart'] = true;455 // since they're grouped, i'm just marking the first one being added456 oObj[_sDOMEvent] = true;457 $.extend(true,_oDatajQueryGestures,oObj);458 _$element.data('ojQueryGestures' ,_oDatajQueryGestures);459 // add gesture events460 if($.hasGestures) {461 switch(_sGestureEvent) {462 // event: orientationchange463 case 'orientationchange':464 _$element.get(0).addEventListener('orientationchange', _onOrientationchange, false);465 break;466 // event:467 // - shake468 // - tilt469 case 'shake':470 case 'shakefrontback':471 case 'shakeleftright':472 case 'shakeupdown':473 case 'tilt':474 //$.hasGyroscope = true //!window.DeviceOrientationEvent;475 //_$element.get(0).addEventListener('devicemotion', _onDevicemotion, false);476 //_$element.get(0).addEventListener('deviceorientation', _onDeviceorientation, false);477 _$element.get(0).addEventListener('devicemotion', _onDevicemotion, false);478 break;479 // event:480 // - touchstart481 // - touchmove482 // - touchend483 case 'tap':484 case 'swipe':485 case 'swipeup':486 case 'swiperightup':487 case 'swiperight':488 case 'swiperightdown':489 case 'swipedown':490 case 'swipeleftdown':491 case 'swipeleft':492 _$element.get(0).addEventListener('touchstart', _onTouchstart, false);493 break;494 // event: gestureend495 case 'pinchopen':496 case 'pinchclose' :497 case 'rotatecw' :498 case 'rotateccw' :499 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);500 _$element.get(0).addEventListener('gestureend', _onGestureend, false);501 break;502 // event: gesturechange503 case 'pinch':504 case 'rotate':505 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);506 _$element.get(0).addEventListener('gesturechange', _onGesturechange, false);507 break;508 }509 }510 // create substitute for gesture events511 else {512 switch(_sGestureEvent) {513 // event substitutes:514 // - touchstart: mousedown515 // - touchmove: none516 // - touchend: mouseup517 case 'tap':518 case 'swipe':519 // _$element.get(0).addEventListener('mousedown', _onTouchstart, false);520 _$element.bind('mousedown', _onTouchstart);521 break;522 // no substitution523 case 'orientationchange':524 case 'pinchopen':525 case 'pinchclose' :526 case 'rotatecw' :527 case 'rotateccw' :528 case 'pinch':529 case 'rotate':530 case 'shake':531 case 'tilt':532 break;533 }534 }535 }536 return false;537 },538 /**539 * For every $.bind(GESTURE) the add-function will be called.540 * Instead of binding an actual eventlister, the event is stored as $.data on the element.541 * The handler will be triggered using $.triggerHandler(GESTURE) if the internal542 * eventhandler (proxy being bound on setup()) detects a GESTURE event543 * @param {Object} event_ jQuery-Event-Object being passed by $.bind()544 * @return {Void}545 */546 add : function(event_) {547 // add pseudo event: properties on $.data548 var _$element = jQuery(this);549 var _oDatajQueryGestures = _$element.data('ojQueryGestures');550// _oDatajQueryGestures[event_.type] = { 'originalType' : event_.type , 'threshold' : event_.data.threshold, 'preventDefault' : event_.data.preventDefault } ;551 _oDatajQueryGestures[event_.type] = { 'originalType' : event_.type } ;552 return false;553 },554 /**555 * For every $.unbind(GESTURE) the remove-function will be called.556 * Instead of removing the actual eventlister, the event is removed from $.data on the element.557 * @param {Object} event_ jQuery-Event-Object being passed by $.bind()558 * @return {Void}559 */560 remove : function(event_) {561 // remove pseudo event: properties on $.data562 var _$element = jQuery(this);563 var _oDatajQueryGestures = _$element.data('ojQueryGestures');564 _oDatajQueryGestures[event_.type] = false;565 _$element.data('ojQueryGestures' ,_oDatajQueryGestures );566 return false;567 },568 /**569 * The last $.unbind()-call on the domElement triggers the teardown function570 * removing the eventlistener571 * @return {Void}572 */573 // @TODO: maybe rework teardown to work with event type?!574 teardown : function() {575 // split the arguments to necessary controll arguements576 var _aSplit = sInternal_.split('_');577 var _sDOMEvent = _aSplit[0]; //578 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour579 var _sGestureEvent = _aSplit[1].slice(0,_aSplit[1].length-2);580 var _$element = jQuery(this);581 var _oDatajQueryGestures;582 var oObj;583 // bind the event handler on the first $.bind() for a gestureend-event, set marker584 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {585 // setup pseudo event586 _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};587 oObj = {};588 // remove marker for: domEvent being set on this element589 oObj[_sDOMEvent] = false;590 $.extend(true,_oDatajQueryGestures,oObj);591 _$element.data('ojQueryGestures' ,_oDatajQueryGestures);592 // remove gesture events593 if($.hasGestures) {594 switch(_sGestureEvent) {595 // event: orientationchange596 case 'orientationchange':597 _$element.get(0).removeEventListener('orientationchange', _onOrientationchange, false);598 break;599 case 'shake':600 case 'shakefrontback':601 case 'shakeleftright':602 case 'shakeupdown':603 case 'tilt':604 _$element.get(0).removeEventListener('devicemotion', _onDevicemotion, false);605 break;606 // event :607 // - touchstart608 // - touchmove609 // - touchend610 case 'tap':611 case 'swipe':612 case 'swipeup':613 case 'swiperightup':614 case 'swiperight':615 case 'swiperightdown':616 case 'swipedown':617 case 'swipeleftdown':618 case 'swipeleft':619 case 'swipeleftup':620 _$element.get(0).removeEventListener('touchstart', _onTouchstart, false);621 _$element.get(0).removeEventListener('touchmove', _onTouchmove, false);622 _$element.get(0).removeEventListener('touchend', _onTouchend, false);623 break;624 // event: gestureend625 case 'pinchopen':626 case 'pinchclose' :627 case 'rotatecw' :628 case 'rotateccw' :629 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);630 _$element.get(0).removeEventListener('gestureend', _onGestureend, false);631 break;632 // event: gesturechange633 case 'pinch':634 case 'rotate':635 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);636 _$element.get(0).removeEventListener('gesturechange', _onGesturechange, false);637 break;638 }639 }640 // remove substitute for gesture events641 else {642 switch(_sGestureEvent) {643 // event substitutes:644 // - touchstart: mousedown645 // - touchmove: none646 // - touchend: mouseup647 case 'tap':648 case 'swipe':649// _$element.get(0).removeEventListener('mousedown', _onTouchstart, false);650// _$element.get(0).removeEventListener('mousemove', _onTouchmove, false);651// _$element.get(0).removeEventListener('mouseup', _onTouchend, false);652 _$element.unbind('mousedown', _onTouchstart);653 _$element.unbind('mousemove', _onTouchmove);654 _$element.unbind('mouseup', _onTouchend);655 break;656 // no substitution657 case 'orientationchange':658 case 'pinchopen':659 case 'pinchclose' :660 case 'rotatecw' :661 case 'rotateccw' :662 case 'pinch':663 case 'rotate':664 case 'shake':665 case 'tilt':666 break;667 }668 }669 }670 return false;671 }672 };673 });674 /**675 * Creates the object that ist passed as second argument to the $element.triggerHandler function.676 * This object contains detailed informations about the gesture event.677 * @param {Object} oOptions_ {type: {String}, touches: {String}, deltaY: {String},deltaX : {String}, startMove: {Object}, event:{DOM-Event}, timestamp:{String},vector: {Number}}678 * @example _createOptions (679 * {680 * type: 'swipemove',681 * touches: '1',682 * deltaY: _iDeltaY,683 * deltaX : _iDeltaX,684 * startMove: _oDatajQueryGestures.oStartTouch,685 * event:event_,686 * timestamp:_oEventData.timestamp,687 * vector: -1688 * }689 * );690 * @returns {Object}691 * {692 * type: eventtype e.g. "swipe","pinch",693 * originalEvent: {DOM-Event},694 * // default: just one entry on the delta-array - the first touchpoint695 * // the first touchpoint is the reference point for every gesture,696 * // because moving touchpoints in various directions would result in697 * // a gesture.698 * // delta and direction details are just provided for touch not for gesture / motion events699 * delta : [700 * {701 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)702 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)703 * moved: {Number}, // distance: relative to the original touchpoint704 * startX: {Number} , // relative to the original touchpoint705 * startY: {Number} ,// relative to the original touchpoint706 * } ],707 * // based on the first touchpoint708 * direction : { // relative to the last touchevent (e.g. touchmove!)709 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)710 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)711 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)712 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)713 * startX: {Number} , //-1,0,+1 relative to the original touchpoint714 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint715 * },716 * rotation: {Number} || null, // gestureonly: amount of rotation relative to the current position NOT the original717 * scale: {Number} || null, // gestureonly: amount of scaling relative to the current position NOT the original718 * duration: {Number}, // ms: relative to the original touchpoint719 * 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 touchpoint720 * };721 */722 function _createOptions(oOptions_) {723 // force properties724 oOptions_.startMove = (oOptions_.startMove) ? oOptions_.startMove : {startX: null,startY:null,timestamp:null} ;725 var _iNow = new Date().getTime();726 var _oDirection;727 var _oDelta;728 // calculate touch differences729 if (oOptions_.touches) {730 // store delta values731 _oDelta = [732 {733 lastX: oOptions_.deltaX ,734 lastY: oOptions_.deltaY,735 moved: null,736 startX: oOptions_.screenX - oOptions_.startMove.screenX ,737 startY: oOptions_.screenY - oOptions_.startMove.screenY738 }739 ];740 _oDirection = {741 vector: oOptions_.vector || null,742 orientation : window.orientation || null,743 lastX : ((_oDelta[0].lastX > 0) ? +1 : ( (_oDelta[0].lastX < 0) ? -1 : 0 ) ),744 lastY : ((_oDelta[0].lastY > 0) ? +1 : ( (_oDelta[0].lastY < 0) ? -1 : 0 ) ),745 startX : ((_oDelta[0].startX > 0) ? +1 : ( (_oDelta[0].startX < 0) ? -1 : 0 ) ),746 startY : ((_oDelta[0].startY > 0) ? +1 : ( (_oDelta[0].startY < 0) ? -1 : 0 ) )747 };748 // calculate distance traveled using the pythagorean theorem749 _oDelta[0].moved = Math.sqrt(Math.pow(Math.abs(_oDelta[0].startX), 2) + Math.pow(Math.abs(_oDelta[0].startY), 2));750 }751 return {752 type: oOptions_.type || null,753 originalEvent: oOptions_.event || null,754 delta : _oDelta || null,755 direction : _oDirection || { orientation : window.orientation || null, vector: oOptions_.vector || null},756 duration: (oOptions_.duration) ? oOptions_.duration : ( oOptions_.startMove.timestamp ) ? _iNow - oOptions_.timestamp : null,757 rotation: oOptions_.rotation || null,758 scale: oOptions_.scale || null,759 description : oOptions_.description || [760 oOptions_.type,761 ':',762 oOptions_.touches,763 ':',764 ((_oDelta[0].lastX != 0) ? ((_oDelta[0].lastX > 0) ? 'right' : 'left') : 'steady'),765 ':',766 ((_oDelta[0].lastY != 0) ? ( (_oDelta[0].lastY > 0) ? 'down' : 'up') :'steady')767 ].join('')768 };769 }770 /**771 * DOM-event handlers772 */773 /**774 * Handler: orientationchange775 * Triggers the bound orientationchange handler on the window element776 * The "orientationchange" handler will receive an object with additional information777 * about the event.778 * {779 * direction : {780 * orientation: {-90|0|90|180}781 * },782 * description : [783 * 'orientationchange:{landscape:clockwise:|portrait:default|landscape:counterclockwise|portrait:upsidedown}:{-90|0|90|180}' // e.g. 'orientation:landscape:clockwise:-90784 * }785 * @param {DOM-Event} event_786 * @return {Void}787 */788 function _onOrientationchange(event_) {789 // window.orientation: -90,0,90,180790 var _aDict = ['landscape:clockwise:','portrait:default:','landscape:counterclockwise:','portrait:upsidedown:'];791 $(window).triggerHandler('orientationchange',792 {793 direction : {orientation: window.orientation},794 description : [795 'orientationchange:',796 _aDict[( (window.orientation / 90) +1)],797 window.orientation798 ].join('')799 });800 }801 /**802 * Handler: devicemotion803 * Calculates "motion events" such as shake, tilt, wiggle by observing "changes in space"804 * For understanding "directions", place your mobile device on a table with the bottom805 * (home button) close to you:806 * - x-axis: horizontal left / right807 * - y-axis: horizontal front / back (through the home button)808 * - z-axis: vertical through your device809 * @param {DOM-Event} event_810 * @returns {Object}811 * {812 * type: eventtype e.g. "shake",813 * originalEvent: {DOM-Event},814 * // delta and direction details are just provided for touch not for gesture / motion events815 * delta : null,816 * direction :{817 * vector: null,818 * orientation: -90,0,90,180 || null (window.orienntation)819 * }820 * rotation: {Number} , // amount of rotation relative to the current position NOT the original821 * scale: {Number} , // amount of scaling relative to the current position NOT the original822 * duration: {Number}, // ms: duration of the motion823 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"824 * };825 * @param {DOM-Event} event_826 * @return {Void}827 */828 function _onDevicemotion(event_) {829 var _sType;830 var _$element = jQuery(window);831 //var _bHasGyroscope = $.hasGyroscope;832 // skip custom notification: devicemotion is triggered every 0.05s regardlesse of any gesture833 // get options834 var _oDatajQueryGestures = _$element.data('ojQueryGestures');835 var _oThreshold = $.jGestures.defaults.thresholdShake;836 // get last position or set initital values837 var _oLastDevicePosition = _oDatajQueryGestures.oDeviceMotionLastDevicePosition || {838 accelerationIncludingGravity : {839 x: 0,840 y: 0,841 z: 0842 },843 shake : {844 eventCount: 0,845 intervalsPassed: 0,846 intervalsFreeze: 0847 },848 shakeleftright : {849 eventCount: 0,850 intervalsPassed: 0,851 intervalsFreeze: 0852 },853 shakefrontback : {854 eventCount: 0,855 intervalsPassed: 0,856 intervalsFreeze: 0857 },858 shakeupdown : {859 eventCount: 0,860 intervalsPassed: 0,861 intervalsFreeze: 0862 }863 };864 // cache current values865 var _oCurrentDevicePosition = {866 accelerationIncludingGravity : {867 x: event_.accelerationIncludingGravity.x,868 y: event_.accelerationIncludingGravity.y,869 z: event_.accelerationIncludingGravity.z870 },871 shake: {872 eventCount: _oLastDevicePosition.shake.eventCount,873 intervalsPassed: _oLastDevicePosition.shake.intervalsPassed,874 intervalsFreeze: _oLastDevicePosition.shake.intervalsFreeze875 },876 shakeleftright: {877 eventCount: _oLastDevicePosition.shakeleftright.eventCount,878 intervalsPassed: _oLastDevicePosition.shakeleftright.intervalsPassed,879 intervalsFreeze: _oLastDevicePosition.shakeleftright.intervalsFreeze880 },881 shakefrontback: {882 eventCount: _oLastDevicePosition.shakefrontback.eventCount,883 intervalsPassed: _oLastDevicePosition.shakefrontback.intervalsPassed,884 intervalsFreeze: _oLastDevicePosition.shakefrontback.intervalsFreeze885 },886 shakeupdown: {887 eventCount: _oLastDevicePosition.shakeupdown.eventCount,888 intervalsPassed: _oLastDevicePosition.shakeupdown.intervalsPassed,889 intervalsFreeze: _oLastDevicePosition.shakeupdown.intervalsFreeze890 }891 };892 // options893 var _aType;894 var _aDescription;895 var _oObj;896 // trigger events for all bound pseudo events on this element897 for (_sType in _oDatajQueryGestures) {898 // get current pseudo event899 // trigger bound events on this element900 switch(_sType) {901 case 'shake':902 case 'shakeleftright':903 case 'shakefrontback':904 case 'shakeupdown':905 // options906 _aType = [];907 _aDescription = [];908 _aType.push(_sType);909 // freeze shake - prevent multiple shake events on one shaking motion (user won't stop shaking immediately)910 if (++_oCurrentDevicePosition[_sType].intervalsFreeze > _oThreshold.freezeShakes && _oCurrentDevicePosition[_sType].intervalsFreeze < (2*_oThreshold.freezeShakes) ) { break; }911 // set control values912 _oCurrentDevicePosition[_sType].intervalsFreeze = 0;913 _oCurrentDevicePosition[_sType].intervalsPassed++;914 // check for shaking motions: massive acceleration changes in every direction915 if ( ( _sType === 'shake' ||_sType === 'shakeleftright' ) && ( _oCurrentDevicePosition.accelerationIncludingGravity.x > _oThreshold.leftright.sensitivity || _oCurrentDevicePosition.accelerationIncludingGravity.x < (-1* _oThreshold.leftright.sensitivity) ) ) {916 _aType.push('leftright');917 _aType.push('x-axis');918 }919 if ( ( _sType === 'shake' ||_sType === 'shakefrontback' ) && (_oCurrentDevicePosition.accelerationIncludingGravity.y > _oThreshold.frontback.sensitivity || _oCurrentDevicePosition.accelerationIncludingGravity.y < (-1 * _oThreshold.frontback.sensitivity) ) ) {920 _aType.push('frontback');921 _aType.push('y-axis');922 }923 if ( ( _sType === 'shake' ||_sType === 'shakeupdown' ) && ( _oCurrentDevicePosition.accelerationIncludingGravity.z+9.81 > _oThreshold.updown.sensitivity || _oCurrentDevicePosition.accelerationIncludingGravity.z+9.81 < (-1 * _oThreshold.updown.sensitivity) ) ) {924 _aType.push('updown');925 _aType.push('z-axis');926 }927 // at least one successful shaking event928 if (_aType.length > 1) {929 // minimum number of shaking motions during the defined "time" (messured by events - device event interval: 0.05s)930 if (++_oCurrentDevicePosition[_sType].eventCount == _oThreshold.requiredShakes && (_oCurrentDevicePosition[_sType].intervalsPassed) < _oThreshold.freezeShakes ) {931 // send event932 _$element.triggerHandler(_sType, _createOptions ({type: _sType, description: _aType.join(':'), event:event_,duration:_oCurrentDevicePosition[_sType].intervalsPassed*5 }) );933 // reset934 _oCurrentDevicePosition[_sType].eventCount = 0;935 _oCurrentDevicePosition[_sType].intervalsPassed = 0;936 // freeze shake937 _oCurrentDevicePosition[_sType].intervalsFreeze = _oThreshold.freezeShakes+1;938 }939 // too slow, reset940 else if (_oCurrentDevicePosition[_sType].eventCount == _oThreshold.requiredShakes && (_oCurrentDevicePosition[_sType].intervalsPassed) > _oThreshold.freezeShakes ) {941 _oCurrentDevicePosition[_sType].eventCount = 0 ;942 _oCurrentDevicePosition[_sType].intervalsPassed = 0;943 }944 }945 break;946 }947 // refresh pseudo events948 _oObj = {};949 _oObj.oDeviceMotionLastDevicePosition = _oCurrentDevicePosition;950 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));951 }952 }953 /**954 * Handler: touchstart or mousedown955 * Setup pseudo-event by storing initial values such as :956 * screenX : {Number}957 * screenY : {Number}958 * timestamp: {Number}959 * on the pseudo gesture event and960 * sets up additional eventlisteners for handling touchmove events.961 * @param {DOM-Event} event_962 * @return {Void}963 */964 function _onTouchstart(event_) {965 // ignore bubbled handlers966 // if ( event_.currentTarget !== event_.target ) { return; }967 var _$element = jQuery(event_.currentTarget);968 // var _$element = jQuery(event_.target);969 // trigger custom notification970 _$element.triggerHandler($.jGestures.events.touchstart,event_);971 // set the necessary touch events972 if($.hasGestures) {973 event_.currentTarget.addEventListener('touchmove', _onTouchmove, false);974 event_.currentTarget.addEventListener('touchend', _onTouchend, false);975 }976 // event substitution977 else {978// event_.currentTarget.addEventListener('mousemove', _onTouchmove, false);979// event_.currentTarget.addEventListener('mouseup', _onTouchend, false);980 _$element.bind('mousemove', _onTouchmove);981 _$element.bind('mouseup', _onTouchend);982 }983 // get stored pseudo event984 var _oDatajQueryGestures = _$element.data('ojQueryGestures');985 // var _oEventData = _oDatajQueryGestures[_sType];986 var _eventBase = (event_.touches) ? event_.touches[0] : event_;987 // store current values for calculating relative values (changes between touchmoveevents)988 var _oObj = {};989 _oObj.oLastSwipemove = { screenX : _eventBase.screenX, screenY : _eventBase.screenY, timestamp:new Date().getTime()};990 _oObj.oStartTouch = { screenX : _eventBase.screenX, screenY : _eventBase.screenY, timestamp:new Date().getTime()};991 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));992 }993 /**994 * Handler: touchmove or mousemove995 * Calculates the x/y changes since the last event,996 * compares it to $.jGestures.defaults.thresholdMove and triggers997 * an swipemove event if the distance exceed the998 * threshold.999 * Custom-event argument object:1000 * {Object}1001 * {1002 * type: e.g. 'swipemove',1003 * ¡Ö: {DOM-Event},1004 * // default: just one entry on the delta-array - the first touchpoint1005 * // the first touchpoint is the reference point for every gesture,1006 * // because moving touchpoints in various directions would result in1007 * // a gesture.1008 * // delta and direction details are just provided for touch not for gesture / motion events1009 * delta : [1010 * {1011 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)1012 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)1013 * moved: {Number}, // distance: relative to the original touchpoint1014 * startX: {Number} , // relative to the original touchpoint1015 * startY: {Number} ,// relative to the original touchpoint1016 * } ],1017 * // based on the first touchpoint1018 * direction : { // relative to the last touchevent (e.g. touchmove!)1019 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1020 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1021 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1022 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1023 * startX: {Number} , //-1,0,+1 relative to the original touchpoint1024 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint1025 * },1026 * rotation: null, // gestureonly: amount of rotation relative to the current position NOT the original1027 * scale: null, // gestureonly: amount of scaling relative to the current position NOT the original1028 * duration: {Number}, // ms: relative to the original touchpoint1029 * 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 touchpoint1030 * };1031 *1032 * @param {DOM-Event} event_1033 * @return {Void}1034 */1035 function _onTouchmove(event_) {1036 var _$element = jQuery(event_.currentTarget);1037 // var _$element = jQuery(event_.target);1038 // get stored pseudo event1039 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1040 var _bHasTouches = !!event_.touches;1041 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;1042 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;1043 //relative to the last event1044 var _oEventData = _oDatajQueryGestures.oLastSwipemove;1045 var _iDeltaX = _iScreenX - _oEventData.screenX ;1046 var _iDeltaY = _iScreenY - _oEventData.screenY;1047 var _oDetails;1048 // there's a swipemove set (not the first occurance), trigger event1049 if (!!_oDatajQueryGestures.oLastSwipemove) {1050 // check1051 _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});1052 _$element.triggerHandler(_oDetails.type,_oDetails);1053 }1054 // store the new values1055 var _oObj = {};1056 var _eventBase = (event_.touches) ? event_.touches[0] : event_;1057 _oObj.oLastSwipemove = { screenX : _eventBase.screenX, screenY : _eventBase.screenY, timestamp:new Date().getTime()};1058 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1059 }1060 /**1061 * Handler: touchend or mouseup1062 * Removes the additional handlers (move/end)1063 * Calculates the x/y changes since the touchstart event1064 * not in relation to the last move event.1065 * Triggers the1066 * swipeone|swipetwo|swipethree|swipefour|1067 * swipeup|swiperightup|swiperight|swiperightdown|swipedown|1068 * swipeleftdown|swipeleft|swipeleftup|1069 * tapone|taptwo|tapthree|tapfour1070 * event.1071 * {Object}1072 * {1073 * type: eventtype e.g. "swipeone","swipeleftdown",1074 * originalEvent: {DOM-Event},1075 * // default: just one entry on the delta-array - the first touchpoint1076 * // the first touchpoint is the reference point for every gesture,1077 * // because moving touchpoints in various directions would result in1078 * // a gesture.1079 * // delta and direction details are just provided for touch not for gesture / motion events1080 * delta : [1081 * {1082 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)1083 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)1084 * moved: {Number}, // distance: relative to the original touchpoint1085 * startX: {Number} , // relative to the original touchpoint1086 * startY: {Number} ,// relative to the original touchpoint1087 * } ],1088 * // based on the first touchpoint1089 * direction : { // relative to the last touchevent (e.g. touchmove!)1090 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1091 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1092 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1093 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)1094 * startX: {Number} , //-1,0,+1 relative to the original touchpoint1095 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint1096 * },1097 * rotation: null,1098 * scale: null ,1099 * duration: {Number}, // ms: relative to the original touchpoint1100 * 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 touchpoint1101 * };1102 * @param {DOM-Event} event_1103 * @return {Void}1104 */1105 function _onTouchend(event_) {1106 // ignore bubbled handlers1107 // if ( event_.currentTarget !== event_.target ) { return; }1108 var _$element = jQuery(event_.currentTarget);1109 var _bHasTouches = !!event_.changedTouches;1110 var _iTouches = (_bHasTouches) ? event_.changedTouches.length : '1';1111 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;1112 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;1113 // trigger custom notification1114 _$element.triggerHandler($.jGestures.events.touchendStart,event_);1115 // var _$element = jQuery(event_.target);1116 // remove events1117 if($.hasGestures) {1118 event_.currentTarget.removeEventListener('touchmove', _onTouchmove, false);1119 event_.currentTarget.removeEventListener('touchend', _onTouchend, false);1120 }1121 // event substitution1122 else {1123// event_.currentTarget.removeEventListener('mousemove', _onTouchmove, false);1124// event_.currentTarget.removeEventListener('mouseup', _onTouchend, false);1125 _$element.unbind('mousemove', _onTouchmove);1126 _$element.unbind('mouseup', _onTouchend);1127 }1128 // get all bound pseudo events1129 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1130 // if the current change on the x/y position is above the defined threshold for moving an element set the moved flag1131 // to distinguish between a moving gesture and a shaking finger trying to tap1132 var _bHasMoved = (1133 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdMove ||1134 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdMove1135 ) ? true : false;1136 // if the current change on the x/y position is above the defined threshold for swiping set the moved flag1137 // to indicate we're dealing with a swipe gesture1138 var _bHasSwipeGesture = (1139 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdSwipe ||1140 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdSwipe1141 ) ? true : false;1142 var _sType;1143 var _oEventData ;1144 var _oDelta;1145 // calculate distances in relation to the touchstart position not the last touchmove event!1146 var _iDeltaX;1147 var _iDeltaY;1148 var _oDetails;1149 var _aDict = ['zero','one','two','three','four'];1150 // swipe marker1151 var _bIsSwipe;1152 // trigger events for all bound pseudo events on this element1153 for (_sType in _oDatajQueryGestures) {1154 // get current pseudo event1155 _oEventData = _oDatajQueryGestures.oStartTouch;1156 _oDelta = {};1157 _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;1158 _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;1159 // calculate distances in relation to the touchstart position not the last touchmove event!1160 _iDeltaX = _iScreenX - _oEventData.screenX ;1161 _iDeltaY = _iScreenY - _oEventData.screenY;1162 _oDetails = _createOptions({type: 'swipe', touches: _iTouches, screenY: _iScreenY,screenX:_iScreenX ,deltaY: _iDeltaY,deltaX : _iDeltaX, startMove:_oEventData, event:event_, timestamp: _oEventData.timestamp });1163 // swipe marker1164 _bIsSwipe = false;1165 // trigger bound events on this element1166 switch(_sType) {1167 case 'swipeone':1168 if( _bHasTouches === false && _iTouches == 1 && _bHasMoved === false){1169 // trigger tapone!1170 break;1171 }1172 if (_bHasTouches===false || ( _iTouches == 1 && _bHasMoved === true && _bHasSwipeGesture===true)) {1173 _bIsSwipe = true;1174 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1175 _$element.triggerHandler(_oDetails.type,_oDetails);1176 }1177 break;1178 case 'swipetwo':1179 if (( _bHasTouches && _iTouches== 2 && _bHasMoved === true && _bHasSwipeGesture===true)) {1180 _bIsSwipe = true;1181 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1182 _$element.triggerHandler(_oDetails.type,_oDetails);1183 }1184 break;1185 case 'swipethree':1186 if ( ( _bHasTouches && _iTouches == 3 && _bHasMoved === true && _bHasSwipeGesture===true)) {1187 _bIsSwipe = true;1188 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1189 _$element.triggerHandler(_oDetails.type,_oDetails);1190 }1191 break;1192 case 'swipefour':1193 if ( ( _bHasTouches && _iTouches == 4 && _bHasMoved === true && _bHasSwipeGesture===true)) {1194 _bIsSwipe = true;1195 _oDetails.type = ['swipe',_aDict[_iTouches]].join('');1196 _$element.triggerHandler(_oDetails.type,_oDetails);1197 }1198 break;1199 case 'swipeup':1200 case 'swiperightup':1201 case 'swiperight':1202 case 'swiperightdown':1203 case 'swipedown':1204 case 'swipeleftdown':1205 case 'swipeleft':1206 case 'swipeleftup':1207 if ( _bHasTouches && _bHasMoved === true && _bHasSwipeGesture===true) {1208 _bIsSwipe = true;1209 _oDetails.type = [1210 'swipe',1211 ((_oDetails.delta[0].lastX != 0) ? ((_oDetails.delta[0].lastX > 0) ? 'right' : 'left') : ''),1212 ((_oDetails.delta[0].lastY != 0) ? ((_oDetails.delta[0].lastY > 0) ? 'down' : 'up') :'')1213 ].join('');1214 _$element.triggerHandler(_oDetails.type, _oDetails);1215 }1216 break;1217 case 'tapone':1218 case 'taptwo':1219 case 'tapthree':1220 case 'tapfour':1221 if (( /* _bHasTouches && */ _bHasMoved !== true && _bIsSwipe !==true) && (_aDict[_iTouches] ==_sType.slice(3)) ) {1222 _oDetails.description = ['tap',_aDict[_iTouches]].join('');1223 _oDetails.type = ['tap',_aDict[_iTouches]].join('');1224 _$element.triggerHandler(_oDetails.type,_oDetails);1225 }1226 break;1227 }1228 // refresh pseudo events1229 var _oObj = {};1230// _oObj[_sType] = false;1231// _oObj.hasTouchmoved = false;1232 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1233 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1234 }1235 _$element.triggerHandler($.jGestures.events.touchendProcessed,event_);1236 }1237 /**1238 * Handler: gesturestart1239 * Setup pseudo-event by storing initial values such as :1240 * timestamp: {Number}1241 * on the pseudo gesture event1242 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1243 * @param {DOM-Event} event_1244 * @return {Void}1245 */1246 function _onGesturestart(event_) {1247 // ignore bubbled handlers1248 // if ( event_.currentTarget !== event_.target ) { return; }1249 var _$element = jQuery(event_.currentTarget);1250 // var _$element = jQuery(event_.target);1251 // trigger custom notification1252 _$element.triggerHandler($.jGestures.events.gesturestart,event_);1253 // get stored pseudo event1254 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1255 // var _oEventData = _oDatajQueryGestures[_sType];1256 // store current values for calculating relative values (changes between touchmoveevents)1257 var _oObj = {};1258 _oObj.oStartTouch = {timestamp:new Date().getTime()};1259 _$element.data('ojQueryGestures',$.extend(true,_oDatajQueryGestures,_oObj));1260 }1261 /**1262 * Handler: gesturechange1263 * Read the event_.scale / event_.rotate values,1264 * an triggers a pinch|rotate event if necessary.1265 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1266 * @returns {Object}1267 * {1268 * type: eventtype e.g. "pinch","rotate",1269 * originalEvent: {DOM-Event},1270 * // delta and direction details are just provided for touch not for gesture / motion events1271 * delta : null,1272 * direction : {1273 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1274 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1275 * },1276 * rotation: {Number} , // amount of rotation relative to the current position NOT the original1277 * scale: {Number} , // amount of scaling relative to the current position NOT the original1278 * duration: {Number}, // ms: relative to the original touchpoint1279 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1280 * };1281 * @param {DOM-Event} event_1282 * @return {Void}1283 */1284 function _onGesturechange(event_) {1285 // ignore bubbled handlers1286 // if ( event_.currentTarget !== event_.target ) { return; }1287 var _$element = jQuery(event_.currentTarget);1288 // var _$element = jQuery(event_.target);1289 var _iDelta,_iDirection,_sDesc,_oDetails;1290 // get all pseudo events1291 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1292 // trigger events for all bound pseudo events on this element1293 var _sType;1294 for (_sType in _oDatajQueryGestures) {1295 // trigger a specific bound event1296 switch(_sType) {1297 case 'pinch':1298 _iDelta = event_.scale;1299 if ( ( ( _iDelta < 1 ) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose) ) || ( ( _iDelta > 1 ) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen) ) ) {1300 _iDirection = (_iDelta < 1 ) ? -1 : +1 ;1301 _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('') });1302 _$element.triggerHandler(_oDetails.type, _oDetails);1303 }1304 break;1305 case 'rotate':1306 _iDelta = event_.rotation;1307 if ( ( ( _iDelta < 1 ) && ( -1*(_iDelta) > $.jGestures.defaults.thresholdRotateccw ) ) || ( ( _iDelta > 1 ) && (_iDelta > $.jGestures.defaults.thresholdRotatecw) ) ) {1308 _iDirection = (_iDelta < 1 ) ? -1 : +1 ;1309 _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('') });1310 _$element.triggerHandler(_oDetails.type, _oDetails);1311 }1312 break;1313 }1314 }1315 }1316 /**1317 * Handler: gestureend1318 * Read the event_.scale / event_.rotate values,1319 * compares it to $.jGestures.defaults.threshold* and triggers1320 * a pinchclose|pinchclose|rotatecw|rotateccw event if the distance exceed the1321 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1322 * * Custom-event argument object:1323 * @returns {Object}1324 * {1325 * type: eventtype e.g. "pinchclose","pinchopen", "rotatecw", "rotateccw",1326 * originalEvent: {DOM-Event},1327 * // delta and direction details are just provided for touch not for gesture / motion events1328 * delta : null,1329 * // based on the first touchpoint1330 * direction : {1331 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1332 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1333 * },1334 * rotation: {Number} , // amount of rotation relative to the current position NOT the original1335 * scale: {Number} , // amount of scaling relative to the current position NOT the original1336 * duration: {Number}, // ms: relative to the original touchpoint1337 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1338 * };1339 * @param {DOM-Event} event_1340 * @return {Void}1341 */1342 function _onGestureend(event_) {1343 // ignore bubbled handlers1344 // if ( event_.currentTarget !== event_.target ) { return; }1345 var _$element = jQuery(event_.currentTarget);1346 // var _$element = jQuery(event_.target);1347 // trigger custom notification1348 _$element.triggerHandler($.jGestures.events.gestureendStart,event_);1349 var _iDelta;1350 var _oDatajQueryGestures = _$element.data('ojQueryGestures');1351 // trigger handler for every bound event1352 var _sType;1353 for (_sType in _oDatajQueryGestures) {1354 switch(_sType) {1355 case 'pinchclose':1356 _iDelta = event_.scale;1357 if (( _iDelta < 1 ) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose)) {1358 _$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' }) );1359 }1360 break;1361 case 'pinchopen':1362 _iDelta = event_.scale;1363 if ( ( _iDelta > 1 ) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen) ) {1364 _$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'}) );1365 }1366 break;1367 case 'rotatecw':1368 _iDelta = event_.rotation;1369 if ( ( _iDelta > 1 ) && (_iDelta > $.jGestures.defaults.thresholdRotatecw) ) {1370 _$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'}) );1371 }1372 break;1373 case 'rotateccw':1374 _iDelta = event_.rotation;1375 if ( ( _iDelta < 1 ) && ( -1*(_iDelta) > $.jGestures.defaults.thresholdRotateccw ) ) {1376 _$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'}) );1377 }1378 break;1379 }1380 }1381 _$element.triggerHandler($.jGestures.events.gestureendProcessed,event_);1382 }1383 }...

Full Screen

Full Screen

jquery.jgestures.js

Source:jquery.jgestures.js Github

copy

Full Screen

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 } ...

Full Screen

Full Screen

jgestures.js

Source:jgestures.js Github

copy

Full Screen

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 }...

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run fMBT automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful