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