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);...
jquery.jgestures.js
Source:jquery.jgestures.js
1/**2 * jGestures: a jQuery plugin for gesture events 3 * Copyright 2010-2011, Neue Digitale / Razorfish GmbH4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 * 14 * @fileOverview15 * Neue Digitale / Razorfish GmbH javascript library: add touch events such as 'pinch', 16 * 'rotate', 'swipe', 'tap' and 'orientationchange' on capable user agents. 17 * For incapable devices there's a basic event substitution: a "tapone" event 18 * can be triggered by "clicking", a "swipeone" by performing a swipe-ish 19 * gesture using the mouse (buttondown - mousemove - buttonup).20 * 21 * This is still a beta version, bugfixes and improvements appreciated.22 * 23 * @author martin.krause@neue-digitale.de24 * @version 0.8725 *26 * @snvauthor $Author: martinkr $27 * @svnversion $Revision: 0 $28 *29 * @requires 30 * jQuery JavaScript Library v1.4.2 - http://jquery.com/31 * Copyright 2010, John Resig32 * Dual licensed under the MIT or GPL Version 2 licenses.33 * http://jquery.org/license34 *35 * 36 * @copyright Neue Digitale / Razorfish GmbH37 * 38 * @example jQuery('#swipe').bind('swipeone',eventHandler);39 * 40 * Notification on native events:41 * On every native touchstart, touchend, gesturestart and gestureend-event, 42 * jgestures triggers a corresponding custom event 43 * (jGestures.touchstart,jGestures.touchend,jGestures.gesturestart and jGestures.gestureend) on the event-element.44 * The eventhandler's second argument represents the original touch event (yes: including all touchpoints).45 * Use this if you need very detailed control e.g. kinetic scrolling or implementing additional gestures.46 * 47 * Every jGesture-eventhandler receives a custom object as second argument 48 * containing the original event (originalEvent property) and processed 49 * information (such as delta values and timesptamp).50 * Example:{ 51 * type: eventtype e.g. "swipe","pinch", 52 originalEvent: {DOM-Event},53* // default: just one entry on the delta-array - the first touchpoint54* // the first touchpoint is the reference point for every gesture, 55* // because moving touchpoints in various directions would result in 56* // a gesture.57* // delta and direction details are just provided for touch not for gesture events58* delta : [ 59* {60* lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)61* lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)62* moved: {Number}, // distance: relative to the original touchpoint 63* startX: {Number} , // relative to the original touchpoint64* startY: {Number} ,// relative to the original touchpoint65* } ],66* // based on the first touchpoint67* direction : { // relative to the last touchevent (e.g. touchmove!)68* vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)69* orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)70* lastX : {Number}, // -1,0,+1 || null (orientationchange) // relative to the last touchevent (e.g. touchmove!)71* lastY : {Number}, // -1,0,+1 || null (orientationchange)// relative to the last touchevent (e.g. touchmove!)72* startX: {Number} , // relative to the original touchpoint73* startY: {Number} ,// relative to the original touchpoint74* },75* rotation: {Number} || {null}, // gestureonly: amount of rotation relative to the current position NOT the original 76* scale: {Number} || {null}, // gestureonly: amount of scaling relative to the current position NOT the original 77* duration: {Number}, // ms: relative to the original touchpoint 78* description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint79* };80 * 81 * Available jGesture-events can be grouped into: 82 *83 * 84 * Device events:85 * The jGesture-Events in this group are triggered by the device.86 * 87 * @event 'orientationchange'88 * The device is turned clockwise or counterclockwise. This event is triggered 89 * by the device and might use an internal gyroscope.90 * obj.description:91 * orientationchange:landscape:clockwise:-9092 * orientationchange:portrait:default:093 * orientationchange:landscape:counterclockwise|portrait:9094 * orientationchange:portrait:upsidedown:18095 *96 *97 * Move events:98 * The jGesture-Events in this group are triggered during the touch/gesture 99 * execution whenever a touchpoint changes. 100 * In contrast to touchend/gestureend-events which are triggered after 101 * the touch/gesture has completed. 102 *103 * @event 'pinch'104 * Is triggered during a pinch gesture (two fingers moving away from or 105 * towards each other).106 * obj.description:107 * pinch:-1:close108 * pinch:+1:open109 * 110 * @event 'rotate'111 * Is triggered during a rotation gesture (two fingers rotating clockwise 112 * or counterclockwise).113 * obj.description:114 * rotate:-1:counterclockwise115 * rotate:+1:+clockwise116 * 117 * @event 'swipemove'118 * Is triggered during a swipe move gesture (finger(s) being moved around 119 * the device, e.g. dragging)120 * obj.description:121 * swipemove:1:left:down122 * swipemove:1:left:up123 * swipemove:1:left:steady124 * swipemove:1:right:down125 * swipemove:1:right:up126 * swipemove:1:right:steady127 * swipemove:2:left:down128 * swipemove:2:left:up129 * swipemove:2:left:steady130 * swipemove:2:right:down131 * swipemove:2:right:up132 * swipemove:2:right:steady133 * swipemove:2:left:down134 * swipemove:3:left:up135 * swipemove:3:left:steady136 * swipemove:3:right:down137 * swipemove:3:right:up138 * swipemove:3:right:steady139 * swipemove:3:left:down140 * swipemove:4:left:up141 * swipemove:4:left:steady142 * swipemove:4:right:down143 * swipemove:4:right:up144 * swipemove:4:right:steady145 *146 * 147 * Toucheend events:148 * The jGesture-Events in this group are triggered after the touch/gesture 149 * has completed. 150 * In contrast to touchmove-events which are triggered during the touch/gesture 151 * execution whenever a touchpoint changes.152 * 153 * @event 'swipeone'154 * Is triggered after a swipe move gesture with one touchpoint (one finger155 * was moved around the device)156 * obj.description:157 * swipeone:1:left:down158 * swipeone:1:left:up159 * swipeone:1:left:steady160 * swipeone:1:right:down161 * swipeone:1:right:up162 * swipeone:1:right:steady163 * 164 * @event 'swipetwo'165 * Is triggered after a swipe move gesture with two touchpoints (two fingers166 * were moved around the device)167 * obj.description:168 * swipetwo:2:left:down169 * swipetwo:2:left:up170 * swipetwo:2:left:steady171 * swipetwo:2:right:down172 * swipetwo:2:right:up173 * swipetwo:2:right:steady174 * 175 * @event 'swipethree'176 * Is triggered after a swipe move gesture with three touchpoints (three 177 * fingers were moved around the device)178 * obj.description:179 * swipethree:3:left:down180 * swipethree:3:left:up181 * swipethree:3:left:steady182 * swipethree:3:right:down183 * swipethree:3:right:up184 * swipethree:3:right:steady185 * 186 * @event 'swipefour'187 * Is triggered after a swipe move gesture with four touchpoints (four 188 * fingers were moved around the device)189 * obj.description:190 * swipefour:4:left:down191 * swipefour:4:left:up192 * swipefour:4:left:steady193 * swipefour:4:right:down194 * swipefour:4:right:up195 * swipefour:4:right:steady196 * 197 * 198 * @event 'swipeup'199 * Is triggered after an strict upwards swipe move gesture 200 * obj.description:201 * swipe:1:steady:up202 * swipe:2:steady:up203 * swipe:3:steady:up204 * swipe:4:steady:up205 *206 * @event 'swiperightup'207 * Is triggered after a rightwards and upwards swipe move gesture 208 * obj.description:209 * swipe:1:right:up210 * swipe:2:right:up211 * swipe:3:right:up212 * swipe:4:right:up 213 * 214 * @event 'swiperight'215 * Is triggered after a strict rightwards swipe move gesture 216 * obj.description:217 * swipe:1:right:steady218 * swipe:2:right:steady219 * swipe:3:right:steady220 * swipe:4:right:steady221 * 222 * @event 'swiperightdown'223 * Is triggered after a rightwards and downwards swipe move gesture 224 * obj.description:225 * swipe:1:right:down226 * swipe:2:right:down227 * swipe:3:right:down228 * swipe:4:right:down229 * 230 * @event 'swipedown'231 * Is triggered after a strict downwards swipe move gesture 232 * obj.description:233 * swipe:1:steady:down234 * swipe:2:steady:down235 * swipe:3:steady:down236 * swipe:4:steady:down237 * 238 * @event 'swipeleftdown'239 * Is triggered after a leftwards and downwards swipe move gesture 240 * obj.description:241 * swipe:1:left:down242 * swipe:2:left:down243 * swipe:3:left:down244 * swipe:4:left:down245 * 246 * @event 'swipeleft'247 * Is triggered after a strict leftwards swipe move gesture 248 * obj.description:249 * swipe:1:left:steady250 * swipe:2:left:steady251 * swipe:3:left:steady252 * swipe:4:left:steady253 * 254 * @event 'swipeleftup'255 * Is triggered after a leftwards and upwards swipe move gesture 256 * obj.description:257 * swipe:1:left:up258 * swipe:2:left:up259 * swipe:3:left:up260 * swipe:4:left:up261 * 262 * @event 'tapone'263 * Is triggered after a single (one finger) tap gesture 264 * obj.description:265 * tapone266* 267 * @event 'taptwo'268 * Is triggered after a double (two finger) tap gesture 269 * obj.description:270 * taptwo271 * * 272 * @event 'tapthree'273 * Is triggered after a tripple (three finger) tap gesture 274 * obj.description:275 * tapthree276 * 277 * 278 * Gestureend events:279 * A gesture is an interpretation of different touchpoints. 280 * The jGesture-Events in this group are triggered when a gesture has finished 281 * and the touchpoints are removed from the device.282 *283 * @event 'pinchopen'284 * Is triggered when a pinchopen gesture (two fingers moving away from each 285 * other) occured and the touchpoints (fingers) are removed the device. 286 * obj.description:287 * pinch:+1:open288 * 289 * @event 'pinchclose'290 * Is triggered when a pinchclose gesture (two fingers moving towards each 291 * other) occured and the touchpoints (fingers) are removed the device. 292 * obj.description:293 * pinch:-1:close294 * 295 * @event 'rotatecw'296 * Is triggered when a clockwise rotation gesture (two fingers rotating 297 * clockwise) occured and the touchpoints (fingers) are removed the device.298 * obj.description:299 * rotate:+1:+clockwise300 * 301 * @event 'rotateccw'302 * Is triggered when a counterclockwise rotation gesture (two fingers 303 * rotating counterclockwise) occured and the touchpoints (fingers) are 304 * removed the device.305 * obj.description:306 * rotate:-1:+counterclockwise307 * 308 * @example309 * .bind( eventType, [ eventData ], handler(eventObject) )310 * jQuery('body').bind('tapone',function(){alert(arguments[1].description);})311 312313 */314315 (function ($) {316317 /**318 * General thresholds.319 */320 $.jGestures = {};321 $.jGestures.defaults = {};322 $.jGestures.defaults.thresholdPinchopen = 0.05;323 $.jGestures.defaults.thresholdPinchmove = 0.05;324 $.jGestures.defaults.thresholdPinch = 0.05;325 $.jGestures.defaults.thresholdPinchclose = 0.05;326 $.jGestures.defaults.thresholdRotatecw = 5; //deg327 $.jGestures.defaults.thresholdRotateccw = 5; // deg328 // a tap becomes a swipe if x/y values changes are above this threshold 329 $.jGestures.defaults.thresholdMove = 20;330 $.jGestures.defaults.thresholdSwipe = 100;331 $.jGestures.data = {};332 // get capable user agents 333 $.jGestures.data.capableDevicesInUserAgentString = ['iPad', 'iPhone', 'iPod', 'Mobile Safari']; // basic functionality such as swipe, pinch, rotate, tap should work on every mobile safari, e.g. GalaxyTab 334 $.jGestures.data.hasGestures = (function () { var _i; for (_i = 0; _i < $.jGestures.data.capableDevicesInUserAgentString.length; _i++) { if (navigator.userAgent.indexOf($.jGestures.data.capableDevicesInUserAgentString[_i]) !== -1) { return true; } } return false; })();335 $.hasGestures = $.jGestures.data.hasGestures;336 $.jGestures.events = {337 touchstart: 'jGestures.touchstart',338 touchendStart: 'jGestures.touchend;start',339 touchendProcessed: 'jGestures.touchend;processed',340 gesturestart: 'jGestures.gesturestart',341 gestureendStart: 'jGestures.gestureend;start',342 gestureendProcessed: 'jGestures.gestureend;processed'343 };344345 jQuery346 .each({347 // "first domevent necessary"_"touch event+counter" : "exposed as"348 // event: orientationchange349 orientationchange_orientationchange01: "orientationchange",350 // event: gestures351 gestureend_pinchopen01: "pinchopen",352 gestureend_pinchclose01: "pinchclose",353 gestureend_rotatecw01: 'rotatecw',354 gestureend_rotateccw01: 'rotateccw',355 // move events356 gesturechange_pinch01: 'pinch',357 gesturechange_rotate01: 'rotate',358 touchstart_swipe13: 'swipemove',359 // event: touches360 touchstart_swipe01: "swipeone",361 touchstart_swipe02: "swipetwo",362 touchstart_swipe03: "swipethree",363 touchstart_swipe04: "swipefour",364 touchstart_swipe05: 'swipeup',365 touchstart_swipe06: 'swiperightup',366 touchstart_swipe07: 'swiperight',367 touchstart_swipe08: 'swiperightdown',368 touchstart_swipe09: 'swipedown',369 touchstart_swipe10: 'swipeleftdown',370 touchstart_swipe11: 'swipeleft',371 touchstart_swipe12: 'swipeleftup',372 touchstart_tap01: 'tapone',373 touchstart_tap02: 'taptwo',374 touchstart_tap03: 'tapthree',375 touchstart_tap04: 'tapfour'376 },377378 /**379 * Add gesture events inside the jQuery.event.special namespace 380 */381 function (sInternal_, sPublicFN_) {382383 // add as funciton to jQuery.event.special.sPublicFN_ 384 jQuery.event.special[sPublicFN_] = {385386 /**387 * When the first event handler is bound, jQuery executes the setup function.388 * This plugin just uses one eventhandler per element, regardless of the number of bound events.389 * All Events are stored internally as properties on the dom-element using the $.data api. 390 * The setup-function adds the eventlistener, acting as a proxy function for the internal events.391 * $.data.ojQueryGestures[_sDOMEvent ('tap') ] = {Boolean}392 * @return {Void}393 */394 setup: function () {395396 // split the arguments to necessary controll arguements397 var _aSplit = sInternal_.split('_');398 var _sDOMEvent = _aSplit[0]; // 399 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour400 var _sGestureEvent = _aSplit[1].slice(0, _aSplit[1].length - 2);401 var _$element = jQuery(this);402 // bind the event handler on the first $.bind() for a gestureend-event, set marker403 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {404 // setup pseudo event405 var _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};406 var oObj = {};407 // marker for: domEvent being set on this element 408 // e.g.: $.data.oGestureInternals['touchstart'] = true;409 // since they're grouped, i'm just marking the first one being added410 oObj[_sDOMEvent] = true;411 $.extend(true, _oDatajQueryGestures, oObj);412 _$element.data('ojQueryGestures', _oDatajQueryGestures);413 // add gesture events414 if ($.hasGestures) {415 switch (_sGestureEvent) {416417 // event: orientationchange 418 case 'orientationchange':419 _$element.get(0).addEventListener('orientationchange', _onOrientationchange, false);420 break;421422 // event: 423 // - touchstart 424 // - touchmove 425 // - touchend 426 case 'tap':427 case 'swipe':428 case 'swipeup':429 case 'swiperightup':430 case 'swiperight':431 case 'swiperightdown':432 case 'swipedown':433 case 'swipeleftdown':434 case 'swipeleft':435 _$element.get(0).addEventListener('touchstart', _onTouchstart, false);436 break;437438 // event: gestureend 439 case 'pinchopen':440 case 'pinchclose':441 case 'rotatecw':442 case 'rotateccw':443 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);444 _$element.get(0).addEventListener('gestureend', _onGestureend, false);445 break;446447 // event: gesturechange 448 case 'pinch':449 case 'rotate':450 _$element.get(0).addEventListener('gesturestart', _onGesturestart, false);451 _$element.get(0).addEventListener('gesturechange', _onGesturechange, false);452 break;453 }454 }455 // create substitute for gesture events 456 else {457 switch (_sGestureEvent) {458 // event substitutes: 459 // - touchstart: mousedown 460 // - touchmove: none 461 // - touchend: mouseup 462 case 'tap':463 case 'swipe':464 // _$element.get(0).addEventListener('mousedown', _onTouchstart, false);465 _$element.bind('mousedown', _onTouchstart);466 break;467468 // no substitution 469 case 'orientationchange':470 case 'pinchopen':471 case 'pinchclose':472 case 'rotatecw':473 case 'rotateccw':474 case 'pinch':475 case 'rotate':476477 break;478 }479 }480481 }482 return false;483 },484485 /**486 * For every $.bind(GESTURE) the add-function will be called.487 * Instead of binding an actual eventlister, the event is stored as $.data on the element.488 * The handler will be triggered using $.triggerHandler(GESTURE) if the internal 489 * eventhandler (proxy being bound on setup()) detects a GESTURE event490 * @param {Object} event_ jQuery-Event-Object being passed by $.bind() 491 * @return {Void}492 */493 add: function (event_) {494 // add pseudo event: properties on $.data 495 var _$element = jQuery(this);496 var _oDatajQueryGestures = _$element.data('ojQueryGestures');497 // _oDatajQueryGestures[event_.type] = { 'originalType' : event_.type , 'threshold' : event_.data.threshold, 'preventDefault' : event_.data.preventDefault } ;498 _oDatajQueryGestures[event_.type] = { 'originalType': event_.type };499 return false;500 },501502 /**503 * For every $.unbind(GESTURE) the remove-function will be called.504 * Instead of removing the actual eventlister, the event is removed from $.data on the element.505 * @param {Object} event_ jQuery-Event-Object being passed by $.bind() 506 * @return {Void}507 */508 remove: function (event_) {509 // remove pseudo event: properties on $.data 510 var _$element = jQuery(this);511 var _oDatajQueryGestures = _$element.data('ojQueryGestures');512 _oDatajQueryGestures[event_.type] = false;513 _$element.data('ojQueryGestures', _oDatajQueryGestures);514 return false;515 },516517 /**518 * The last $.unbind()-call on the domElement triggers the teardown function 519 * removing the eventlistener520 * @return {Void}521 */522 // @TASK: maybe rework teardown to work with event type?!523 teardown: function () {524 // split the arguments to necessary controll arguements525 var _aSplit = sInternal_.split('_');526 var _sDOMEvent = _aSplit[0]; // 527 // get the associated gesture event and strip the counter: necessary for distinguisihng similliar events such as tapone-tapfour528 var _sGestureEvent = _aSplit[1].slice(0, _aSplit[1].length - 2);529 var _$element = jQuery(this);530 // bind the event handler on the first $.bind() for a gestureend-event, set marker531 if (!_$element.data('ojQueryGestures') || !_$element.data('ojQueryGestures')[_sDOMEvent]) {532 // setup pseudo event533 var _oDatajQueryGestures = _$element.data('ojQueryGestures') || {};534 var oObj = {};535 // remove marker for: domEvent being set on this element 536 oObj[_sDOMEvent] = false;537 $.extend(true, _oDatajQueryGestures, oObj);538 _$element.data('ojQueryGestures', _oDatajQueryGestures);539540 // remove gesture events541 if ($.hasGestures) {542 switch (_sGestureEvent) {543544 // event: orientationchange 545 case 'orientationchange':546 _$element.get(0).removeEventListener('orientationchange', _onOrientationchange, false);547 break;548549 // event : 550 // - touchstart 551 // - touchmove 552 // - touchend 553 case 'tap':554 case 'swipe':555 case 'swipeup':556 case 'swiperightup':557 case 'swiperight':558 case 'swiperightdown':559 case 'swipedown':560 case 'swipeleftdown':561 case 'swipeleft':562 case 'swipeleftup':563 _$element.get(0).removeEventListener('touchstart', _onTouchstart, false);564 _$element.get(0).removeEventListener('touchmove', _onTouchmove, false);565 _$element.get(0).removeEventListener('touchend', _onTouchend, false);566 break;567568 // event: gestureend 569 case 'pinchopen':570 case 'pinchclose':571 case 'rotatecw':572 case 'rotateccw':573 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);574 _$element.get(0).removeEventListener('gestureend', _onGestureend, false);575 break;576577 // event: gesturechange 578 case 'pinch':579 case 'rotate':580 _$element.get(0).removeEventListener('gesturestart', _onGesturestart, false);581 _$element.get(0).removeEventListener('gesturechange', _onGesturechange, false);582 break;583 }584 }585 // remove substitute for gesture events 586 else {587 switch (_sGestureEvent) {588 // event substitutes: 589 // - touchstart: mousedown 590 // - touchmove: none 591 // - touchend: mouseup 592 case 'tap':593 case 'swipe':594 // _$element.get(0).removeEventListener('mousedown', _onTouchstart, false);595 // _$element.get(0).removeEventListener('mousemove', _onTouchmove, false);596 // _$element.get(0).removeEventListener('mouseup', _onTouchend, false);597 _$element.unbind('mousedown', _onTouchstart);598 _$element.unbind('mousemove', _onTouchmove);599 _$element.unbind('mouseup', _onTouchend);600 break;601602 // no substitution 603 case 'orientationchange':604 case 'pinchopen':605 case 'pinchclose':606 case 'rotatecw':607 case 'rotateccw':608 case 'pinch':609 case 'rotate':610611 break;612 }613 }614615 }616 return false;617 }618619 };620 });621622 /**623 * Creates the object that ist passed as second argument to the $element.triggerHandler function.624 * This object contains detailed informations about the gesture event.625 * @param {Object} oOptions_ {type: {String}, touches: {String}, deltaY: {String},deltaX : {String}, startMove: {Object}, event:{DOM-Event}, timestamp:{String},vector: {Number}}626 * @example _createOptions (627 * { 628 * type: 'swipemove', 629 * touches: '1', 630 * deltaY: _iDeltaY,631 * deltaX : _iDeltaX, 632 * startMove: _oDatajQueryGestures.oStartTouch, 633 * event:event_, 634 * timestamp:_oEventData.timestamp,635 * vector: -1636 * }637 * );638 * @returns {Object} 639 * {640 * type: eventtype e.g. "swipe","pinch",641 * originalEvent: {DOM-Event},642 * // default: just one entry on the delta-array - the first touchpoint643 * // the first touchpoint is the reference point for every gesture, 644 * // because moving touchpoints in various directions would result in 645 * // a gesture.646 * // delta and direction details are just provided for touch not for gesture events647 * delta : [ 648 * {649 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)650 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)651 * moved: {Number}, // distance: relative to the original touchpoint 652 * startX: {Number} , // relative to the original touchpoint653 * startY: {Number} ,// relative to the original touchpoint654 * } ],655 * // based on the first touchpoint656 * direction : { // relative to the last touchevent (e.g. touchmove!)657 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)658 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)659 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)660 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)661 * startX: {Number} , //-1,0,+1 relative to the original touchpoint662 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint663 * },664 * rotation: {Number} || {null}, // gestureonly: amount of rotation relative to the current position NOT the original 665 * scale: {Number} || {null}, // gestureonly: amount of scaling relative to the current position NOT the original 666 * duration: {Number}, // ms: relative to the original touchpoint 667 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint668 * };669 */670 function _createOptions(oOptions_) {671 // force properties672 oOptions_.startMove = (oOptions_.startMove) ? oOptions_.startMove : { startX: null, startY: null, timestamp: null };673 var _iNow = new Date().getTime();674675 // calculate touch differences 676 if (oOptions_.touches) {677 // store delta values678 var _oDelta = [679 {680 lastX: oOptions_.deltaX,681 lastY: oOptions_.deltaY,682 moved: null,683 startX: oOptions_.screenX - oOptions_.startMove.screenX,684 startY: oOptions_.screenY - oOptions_.startMove.screenY685 }686 ];687688 var _oDirection = {689 vector: oOptions_.vector,690 orientation: window.orientation || null,691 lastX: ((_oDelta[0].lastX > 0) ? +1 : ((_oDelta[0].lastX < 0) ? -1 : 0)),692 lastY: ((_oDelta[0].lastY > 0) ? +1 : ((_oDelta[0].lastY < 0) ? -1 : 0)),693 startX: ((_oDelta[0].startX > 0) ? +1 : ((_oDelta[0].startX < 0) ? -1 : 0)),694 startY: ((_oDelta[0].startY > 0) ? +1 : ((_oDelta[0].startY < 0) ? -1 : 0))695 };696697 // calculate distance traveled using the pythagorean theorem 698 _oDelta[0].moved = Math.sqrt(Math.pow(Math.abs(_oDelta[0].startX), 2) + Math.pow(Math.abs(_oDelta[0].startY), 2));699700 }701 return {702 type: oOptions_.type || null,703 originalEvent: oOptions_.event || null,704 delta: _oDelta || null,705 direction: _oDirection || { orientation: window.orientation || null, vector: oOptions_.vector || null },706 duration: (oOptions_.startMove.timestamp) ? _iNow - oOptions_.timestamp : null,707 rotation: oOptions_.rotation || null,708 scale: oOptions_.scale || null,709 description: oOptions_.description || [710 oOptions_.type,711 ':',712 oOptions_.touches,713 ':',714 ((_oDelta[0].lastX != 0) ? ((_oDelta[0].lastX > 0) ? 'right' : 'left') : 'steady'),715 ':',716 ((_oDelta[0].lastY != 0) ? ((_oDelta[0].lastY > 0) ? 'down' : 'up') : 'steady')717 ].join('')718 };719720 }721722723724 /**725 * DOM-event handlers726 */727728 /**729 * Handler: orientationchange730 * Triggers the bound orientationchange handler on the window element731 * The "orientationchange" handler will receive an object with additional information732 * about the event.733 * {734 * direction : {735 * orientation: {-90|0|90|180}736 * },737 * description : [738 * 'orientationchange:{landscape:clockwise:|portrait:default|landscape:counterclockwise|portrait:upsidedown}:{-90|0|90|180}' // e.g. 'orientation:landscape:clockwise:-90739 * }740 * @param {DOM-Event} event_741 * @return {Void}742 */743 function _onOrientationchange(event_) {744745 // window.orientation: -90,0,90,180746 var _aDict = ['landscape:clockwise:', 'portrait:default:', 'landscape:counterclockwise:', 'portrait:upsidedown:'];747748 $(window).triggerHandler('orientationchange',749 {750 direction: { orientation: window.orientation },751 description: [752 'orientationchange:',753 _aDict[((window.orientation / 90) + 1)],754 window.orientation755 ].join('')756 });757 }758759760 /**761 * Handler: touchstart or mousedown762 * Setup pseudo-event by storing initial values such as :763 * screenX : {Number}764 * screenY : {Number}765 * timestamp: {Number}766 * on the pseudo gesture event and 767 * sets up additional eventlisteners for handling touchmove events.768 * @param {DOM-Event} event_769 * @return {Void}770 */771 function _onTouchstart(event_) {772773 // ignore bubbled handlers774 // if ( event_.currentTarget !== event_.target ) { return; }775776 var _$element = jQuery(event_.currentTarget);777 // var _$element = jQuery(event_.target); 778779 // trigger custom notification780 _$element.triggerHandler($.jGestures.events.touchstart, event_);781782783 // set the necessary touch events784 if ($.hasGestures) {785 event_.currentTarget.addEventListener('touchmove', _onTouchmove, false);786 event_.currentTarget.addEventListener('touchend', _onTouchend, false);787 }788 // event substitution789 else {790 // event_.currentTarget.addEventListener('mousemove', _onTouchmove, false);791 // event_.currentTarget.addEventListener('mouseup', _onTouchend, false);792 _$element.bind('mousemove', _onTouchmove);793 _$element.bind('mouseup', _onTouchend);794 }795796 // get stored pseudo event797 var _oDatajQueryGestures = _$element.data('ojQueryGestures');798799 // var _oEventData = _oDatajQueryGestures[_sType];800 var _eventBase = (event_.touches) ? event_.touches[0] : event_;801 // store current values for calculating relative values (changes between touchmoveevents)802 var _oObj = {};803 _oObj.oLastSwipemove = { screenX: _eventBase.screenX, screenY: _eventBase.screenY, timestamp: new Date().getTime() };804 _oObj.oStartTouch = { screenX: _eventBase.screenX, screenY: _eventBase.screenY, timestamp: new Date().getTime() };805806 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));807 }808809810 /**811 * Handler: touchmove or mousemove812 * Calculates the x/y changes since the last event, 813 * compares it to $.jGestures.defaults.thresholdMove and triggers 814 * an swipemove event if the distance exceed the 815 * threshold.816 * Custom-event argument object: 817 * {Object} 818 * {819 * type: e.g. 'swipemove',820 * â: {DOM-Event},821 * // default: just one entry on the delta-array - the first touchpoint822 * // the first touchpoint is the reference point for every gesture, 823 * // because moving touchpoints in various directions would result in 824 * // a gesture.825 * // delta and direction details are just provided for touch not for gesture events826 * delta : [ 827 * {828 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)829 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)830 * moved: {Number}, // distance: relative to the original touchpoint 831 * startX: {Number} , // relative to the original touchpoint832 * startY: {Number} ,// relative to the original touchpoint833 * } ],834 * // based on the first touchpoint835 * direction : { // relative to the last touchevent (e.g. touchmove!)836 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)837 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)838 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)839 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)840 * startX: {Number} , //-1,0,+1 relative to the original touchpoint841 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint842 * },843 * rotation: {null}, // gestureonly: amount of rotation relative to the current position NOT the original 844 * scale: {null}, // gestureonly: amount of scaling relative to the current position NOT the original 845 * duration: {Number}, // ms: relative to the original touchpoint 846 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint847 * };848 * description : {String} // details as String: swipemove:1:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipemove:1:left:steady"849 * };850 * @param {DOM-Event} event_851 * @return {Void}852 */853 function _onTouchmove(event_) {854855 var _$element = jQuery(event_.currentTarget);856 // var _$element = jQuery(event_.target); 857858 // get stored pseudo event859 var _oDatajQueryGestures = _$element.data('ojQueryGestures');860861 var _bHasTouches = !!event_.touches;862 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;863 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;864865 //relative to the last event866 var _oEventData = _oDatajQueryGestures.oLastSwipemove;867 var _iDeltaX = _iScreenX - _oEventData.screenX;868 var _iDeltaY = _iScreenY - _oEventData.screenY;869870 // there's a swipemove set (not the first occurance), trigger event 871 if (!!_oDatajQueryGestures.oLastSwipemove) {872 // check 873 var _oDetails = _createOptions({ type: 'swipemove', touches: (_bHasTouches) ? event_.touches.length : '1', screenY: _iScreenY, screenX: _iScreenX, deltaY: _iDeltaY, deltaX: _iDeltaX, startMove: _oEventData, event: event_, timestamp: _oEventData.timestamp });874 _$element.triggerHandler(_oDetails.type, _oDetails);875 }876 // store the new values877 var _oObj = {};878 var _eventBase = (event_.touches) ? event_.touches[0] : event_;879 _oObj.oLastSwipemove = { screenX: _eventBase.screenX, screenY: _eventBase.screenY, timestamp: new Date().getTime() };880 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));881 }882883884 /**885 * Handler: touchend or mouseup886 * Removes the additional handlers (move/end)887 * Calculates the x/y changes since the touchstart event888 * not in relation to the last move event.889 * Triggers the 890 * swipeone|swipetwo|swipethree|swipefour|891 * swipeup|swiperightup|swiperight|swiperightdown|swipedown|892 * swipeleftdown|swipeleft|swipeleftup|893 * tapone|taptwo|tapthree|tapfour 894 * event.895 * {Object} 896 * {897 * type: eventtype e.g. "swipeone","swipeleftdown",898 * originalEvent: {DOM-Event},899 * // default: just one entry on the delta-array - the first touchpoint900 * // the first touchpoint is the reference point for every gesture, 901 * // because moving touchpoints in various directions would result in 902 * // a gesture.903 * // delta and direction details are just provided for touch not for gesture events904 * delta : [ 905 * {906 * lastX:{Number} , // x-axis: relative to the last touchevent (e.g. touchmove!)907 * lastY:{Number}, // y-axis: relative to the last touchevent (e.g. touchmove!)908 * moved: {Number}, // distance: relative to the original touchpoint 909 * startX: {Number} , // relative to the original touchpoint910 * startY: {Number} ,// relative to the original touchpoint911 * } ],912 * // based on the first touchpoint913 * direction : { // relative to the last touchevent (e.g. touchmove!)914 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)915 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)916 * lastX : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)917 * lastY : {Number}, // -1,0,+1 relative to the last touchevent (e.g. touchmove!)918 * startX: {Number} , //-1,0,+1 relative to the original touchpoint919 * startY: {Number} ,// -1,0,+1 relative to the original touchpoint920 * },921 * rotation: {null}, 922 * scale: {null} , 923 * duration: {Number}, // ms: relative to the original touchpoint 924 * description : {String} // details as String: {TYPE *}:{TOUCHES 1|2|3|4}:{X-AXIS 'right'|'left'|'steady'}:{Y-AXIS 'down'|'up'|'steady'} e.g. "swipe:1:left:steady" relative to the last touchpoint925 * };926 * @param {DOM-Event} event_927 * @return {Void}928 */929 function _onTouchend(event_) {930931 // ignore bubbled handlers932 // if ( event_.currentTarget !== event_.target ) { return; }933934 var _$element = jQuery(event_.currentTarget);935 var _bHasTouches = !!event_.changedTouches;936 var _iTouches = (_bHasTouches) ? event_.changedTouches.length : '1';937 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;938 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;939940 // trigger custom notification941 _$element.triggerHandler($.jGestures.events.touchendStart, event_);942943 // var _$element = jQuery(event_.target); 944 // remove events945 if ($.hasGestures) {946 event_.currentTarget.removeEventListener('touchmove', _onTouchmove, false);947 event_.currentTarget.removeEventListener('touchend', _onTouchend, false);948 }949 // event substitution950 else {951 // event_.currentTarget.removeEventListener('mousemove', _onTouchmove, false);952 // event_.currentTarget.removeEventListener('mouseup', _onTouchend, false);953 _$element.unbind('mousemove', _onTouchmove);954 _$element.unbind('mouseup', _onTouchend);955 }956 // get all bound pseudo events957 var _oDatajQueryGestures = _$element.data('ojQueryGestures');958959 // if the current change on the x/y position is above the defined threshold for moving an element set the moved flag 960 // to distinguish between a moving gesture and a shaking finger trying to tap961 var _bHasMoved = (962 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdMove ||963 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdMove964 ) ? true : false;965966 // if the current change on the x/y position is above the defined threshold for swiping set the moved flag 967 // to indicate we're dealing with a swipe gesture968 var _bHasSwipeGesture = (969 Math.abs(_oDatajQueryGestures.oStartTouch.screenX - _iScreenX) > $.jGestures.defaults.thresholdSwipe ||970 Math.abs(_oDatajQueryGestures.oStartTouch.screenY - _iScreenY) > $.jGestures.defaults.thresholdSwipe971 ) ? true : false;972973974 var _sType;975 // trigger events for all bound pseudo events on this element 976 for (_sType in _oDatajQueryGestures) {977978 // get current pseudo event979 var _oEventData = _oDatajQueryGestures.oStartTouch;980981 var _oDelta = {};982 var _iScreenX = (_bHasTouches) ? event_.changedTouches[0].screenX : event_.screenX;983 var _iScreenY = (_bHasTouches) ? event_.changedTouches[0].screenY : event_.screenY;984 // calculate distances in relation to the touchstart position not the last touchmove event!985 var _iDeltaX = _iScreenX - _oEventData.screenX;986 var _iDeltaY = _iScreenY - _oEventData.screenY;987 var _oDetails = _createOptions({ type: 'swipe', touches: _iTouches, screenY: _iScreenY, screenX: _iScreenX, deltaY: _iDeltaY, deltaX: _iDeltaX, startMove: _oEventData, event: event_, timestamp: _oEventData.timestamp });988989 var _aDict = ['zero', 'one', 'two', 'three', 'four'];990991 // swipe marker992 var _bIsSwipe = false;993994 // trigger bound events on this element995 switch (_sType) {996 case 'swipeone':997998 if (_bHasTouches === false && _iTouches == 1 && _bHasMoved === false) {999 // trigger tapone!1000 break;1001 }1002 if (_bHasTouches === false || (_iTouches == 1 && _bHasMoved === true && _bHasSwipeGesture === true)) {1003 _bIsSwipe = true;10041005 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1006 _$element.triggerHandler(_oDetails.type, _oDetails);1007 }1008 break;10091010 case 'swipetwo':1011 if ((_bHasTouches && _iTouches == 2 && _bHasMoved === true && _bHasSwipeGesture === true)) {1012 _bIsSwipe = true;1013 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1014 _$element.triggerHandler(_oDetails.type, _oDetails);1015 }1016 break;10171018 case 'swipethree':1019 if ((_bHasTouches && _iTouches == 3 && _bHasMoved === true && _bHasSwipeGesture === true)) {1020 _bIsSwipe = true;1021 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1022 _$element.triggerHandler(_oDetails.type, _oDetails);1023 }1024 break;10251026 case 'swipefour':1027 if ((_bHasTouches && _iTouches == 4 && _bHasMoved === true && _bHasSwipeGesture === true)) {1028 _bIsSwipe = true;1029 _oDetails.type = ['swipe', _aDict[_iTouches]].join('');1030 _$element.triggerHandler(_oDetails.type, _oDetails);1031 }1032 break;10331034 case 'swipeup':1035 case 'swiperightup':1036 case 'swiperight':1037 case 'swiperightdown':1038 case 'swipedown':1039 case 'swipeleftdown':1040 case 'swipeleft':1041 case 'swipeleftup':1042 if (_bHasTouches && _bHasMoved === true && _bHasSwipeGesture === true) {1043 _bIsSwipe = true;1044 _oDetails.type = [1045 'swipe',1046 ((_oDetails.delta[0].lastX != 0) ? ((_oDetails.delta[0].lastX > 0) ? 'right' : 'left') : ''),1047 ((_oDetails.delta[0].lastY != 0) ? ((_oDetails.delta[0].lastY > 0) ? 'down' : 'up') : '')1048 ].join('');1049 if (_sType == _oDetails.type) {1050 _$element.triggerHandler(_oDetails.type, _oDetails);1051 }1052 }1053 break;10541055 case 'tapone':1056 case 'taptwo':1057 case 'tapthree':1058 case 'tapfour':1059 if (( /* _bHasTouches && */_bHasMoved !== true && _bIsSwipe !== true) && (_aDict[_iTouches] == _sType.slice(3))) {1060 _oDetails.description = ['tap', _aDict[_iTouches]].join('');1061 _oDetails.type = ['tap', _aDict[_iTouches]].join('');1062 _$element.triggerHandler(_oDetails.type, _oDetails);1063 }1064 break;10651066 }10671068 // refresh pseudo events1069 var _oObj = {};1070 // _oObj[_sType] = false;1071 // _oObj.hasTouchmoved = false;1072 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));1073 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));10741075 }1076 _$element.triggerHandler($.jGestures.events.touchendProcessed, event_);1077 }107810791080 /**1081 * Handler: gesturestart1082 * Setup pseudo-event by storing initial values such as :1083 * timestamp: {Number}1084 * on the pseudo gesture event1085 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated 1086 * @param {DOM-Event} event_1087 * @return {Void}1088 */1089 function _onGesturestart(event_) {10901091 // ignore bubbled handlers1092 // if ( event_.currentTarget !== event_.target ) { return; }10931094 var _$element = jQuery(event_.currentTarget);1095 // var _$element = jQuery(event_.target); 10961097 // trigger custom notification1098 _$element.triggerHandler($.jGestures.events.gesturestart, event_);109911001101 // get stored pseudo event1102 var _oDatajQueryGestures = _$element.data('ojQueryGestures');11031104 // var _oEventData = _oDatajQueryGestures[_sType];1105 // store current values for calculating relative values (changes between touchmoveevents)1106 var _oObj = {};1107 _oObj.oStartTouch = { timestamp: new Date().getTime() };1108 _$element.data('ojQueryGestures', $.extend(true, _oDatajQueryGestures, _oObj));1109 }11101111 /**1112 * Handler: gesturechange1113 * Read the event_.scale / event_.rotate values,1114 * an triggers a pinch|rotate event if necessary.1115 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1116 * @returns {Object} 1117 * {1118 * type: eventtype e.g. "pinch","rotate",1119 * originalEvent: {DOM-Event},1120 * // delta and direction details are just provided for touch not for gesture events1121 * delta : null,1122 * direction :null,1123 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1124 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1125 * rotation: {Number} , // amount of rotation relative to the current position NOT the original 1126 * scale: {Number} , // amount of scaling relative to the current position NOT the original 1127 * duration: {Number}, // ms: relative to the original touchpoint 1128 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1129 * };1130 * @param {DOM-Event} event_1131 * @return {Void}1132 */1133 function _onGesturechange(event_) {11341135 // ignore bubbled handlers1136 // if ( event_.currentTarget !== event_.target ) { return; }11371138 var _$element = jQuery(event_.currentTarget);1139 // var _$element = jQuery(event_.target); 1140 var _iDelta, _iDirection, _sDesc, _oDetails;1141 // get all pseudo events1142 var _oDatajQueryGestures = _$element.data('ojQueryGestures');11431144 // trigger events for all bound pseudo events on this element1145 var _sType;1146 for (_sType in _oDatajQueryGestures) {11471148 // trigger a specific bound event1149 switch (_sType) {11501151 case 'pinch':1152 _iDelta = event_.scale;1153 if (((_iDelta < 1) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose)) || ((_iDelta > 1) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen))) {1154 _iDirection = (_iDelta < 1) ? -1 : +1;1155 _oDetails = _createOptions({ type: 'pinch', scale: _iDelta, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, vector: _iDirection, description: ['pinch:', _iDirection, ':', ((_iDelta < 1) ? 'close' : 'open')].join('') });1156 _$element.triggerHandler(_oDetails.type, _oDetails);1157 }1158 break;11591160 case 'rotate':1161 _iDelta = event_.rotation;1162 if (((_iDelta < 1) && (-1 * (_iDelta) > $.jGestures.defaults.thresholdRotateccw)) || ((_iDelta > 1) && (_iDelta > $.jGestures.defaults.thresholdRotatecw))) {1163 _iDirection = (_iDelta < 1) ? -1 : +1;1164 _oDetails = _createOptions({ type: 'rotate', rotation: _iDelta, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, vector: _iDirection, description: ['rotate:', _iDirection, ':', ((_iDelta < 1) ? 'counterclockwise' : 'clockwise')].join('') });1165 _$element.triggerHandler(_oDetails.type, _oDetails);1166 }1167 break;11681169 }1170 }11711172 }117311741175 /**1176 * Handler: gestureend1177 * Read the event_.scale / event_.rotate values,1178 * compares it to $.jGestures.defaults.threshold* and triggers 1179 * a pinchclose|pinchclose|rotatecw|rotateccw event if the distance exceed the 1180 * Since the gesture-event doesn't supply event.touches no tuchpoints will be calculated1181 * * Custom-event argument object: 1182 * @returns {Object} 1183 * {1184 * type: eventtype e.g. "pinchclose","pinchopen", "rotatecw", "rotateccw",1185 * originalEvent: {DOM-Event},1186 * // delta and direction details are just provided for touch not for gesture events1187 * delta : null,1188 * // based on the first touchpoint1189 * direction : null // relative to the last touchevent (e.g. touchmove!)1190 * vector: {Number}, // -1|+1, indicates the direction if necessary(pinch/rotate)1191 * orientation: {Number} // window.orientation: -90,0,90,180 || null (window.orienntation)1192 * rotation: {Number} , // amount of rotation relative to the current position NOT the original 1193 * scale: {Number} , // amount of scaling relative to the current position NOT the original 1194 * duration: {Number}, // ms: relative to the original touchpoint 1195 * description : {String} // details as String: pinch:{'close'|'open'} e.g. "pinch:-1:close" || rotate:{'counterclockwise'|'clockwise'} e.g. "rotate:-1:counterclockwise"1196 * };1197 * @param {DOM-Event} event_1198 * @return {Void}1199 */1200 function _onGestureend(event_) {1201 // ignore bubbled handlers1202 // if ( event_.currentTarget !== event_.target ) { return; }12031204 var _$element = jQuery(event_.currentTarget);1205 // var _$element = jQuery(event_.target);12061207 // trigger custom notification1208 _$element.triggerHandler($.jGestures.events.gestureendStart, event_);12091210 var _iDelta;1211 var _oDatajQueryGestures = _$element.data('ojQueryGestures');12121213 // trigger handler for every bound event1214 var _sType;1215 for (_sType in _oDatajQueryGestures) {12161217 switch (_sType) {12181219 case 'pinchclose':1220 _iDelta = event_.scale;1221 if ((_iDelta < 1) && (_iDelta % 1) < (1 - $.jGestures.defaults.thresholdPinchclose)) {1222 _$element.triggerHandler('pinchclose', _createOptions({ type: 'pinchclose', scale: _iDelta, vector: -1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'pinch:-1:close' }));1223 }1224 break;12251226 case 'pinchopen':1227 _iDelta = event_.scale;1228 if ((_iDelta > 1) && (_iDelta % 1) > ($.jGestures.defaults.thresholdPinchopen)) {1229 _$element.triggerHandler('pinchopen', _createOptions({ type: 'pinchopen', scale: _iDelta, vector: +1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'pinch:+1:open' }));1230 }1231 break;12321233 case 'rotatecw':1234 _iDelta = event_.rotation;1235 if ((_iDelta > 1) && (_iDelta > $.jGestures.defaults.thresholdRotatecw)) {1236 _$element.triggerHandler('rotatecw', _createOptions({ type: 'rotatecw', rotation: _iDelta, vector: +1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'rotate:+1:clockwise' }));1237 }1238 break;12391240 case 'rotateccw':1241 _iDelta = event_.rotation;1242 if ((_iDelta < 1) && (-1 * (_iDelta) > $.jGestures.defaults.thresholdRotateccw)) {1243 _$element.triggerHandler('rotateccw', _createOptions({ type: 'rotateccw', rotation: _iDelta, vector: -1, touches: null, startMove: _oDatajQueryGestures.oStartTouch, event: event_, timestamp: _oDatajQueryGestures.oStartTouch.timestamp, description: 'rotate:-1:counterclockwise' }));1244 }1245 break;12461247 }1248 }1249 _$element.triggerHandler($.jGestures.events.gestureendProcessed, event_);1250 }1251 }
...
jgestures.js
Source:jgestures.js
1/**2 * jGestures: a jQuery plugin for gesture events3 * Copyright 2010-2011 Neue Digitale / Razorfish GmbH4 * Copyright 2011-2012, Razorfish GmbH5 * Licensed under the Apache License, Version 2.0 (the "License");6 * you may not use this file except in compliance with the License.7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.08 * Unless required by applicable law or agreed to in writing, software9 * distributed under the License is distributed on an "AS IS" BASIS,10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11 * See the License for the specific language governing permissions and12 * limitations under the License.13 * @copyright Razorfish GmbH14 * @author martin.krause@razorfish.de15 * @version 0.90-shake16 * @requires jQuery JavaScript Library v1.4.2 - http://jquery.com/- Copyright 2010, John Resig- Dual licensed under the MIT or GPL Version 2 licenses. http://jquery.org/license17 */18(function(c) {19 c.jGestures = {};20 c.jGestures.defaults = {};21 c.jGestures.defaults.thresholdShake = {22 requiredShakes: 10,23 freezeShakes: 100,24 frontback: {25 sensitivity: 1026 },27 leftright: {28 sensitivity: 1029 },30 updown: {31 sensitivity: 1032 }33 };34 c.jGestures.defaults.thresholdPinchopen = 0.05;35 c.jGestures.defaults.thresholdPinchmove = 0.05;36 c.jGestures.defaults.thresholdPinch = 0.05;37 c.jGestures.defaults.thresholdPinchclose = 0.05;38 c.jGestures.defaults.thresholdRotatecw = 5;39 c.jGestures.defaults.thresholdRotateccw = 5;40 c.jGestures.defaults.thresholdMove = 20;41 c.jGestures.defaults.thresholdSwipe = 100;42 c.jGestures.data = {};43 c.jGestures.data.capableDevicesInUserAgentString = ["iPad", "iPhone", "iPod", "Mobile Safari"];44 c.jGestures.data.hasGestures = (function() {45 var k;46 for (k = 0; k < c.jGestures.data.capableDevicesInUserAgentString.length; k++) {47 if (navigator.userAgent.indexOf(c.jGestures.data.capableDevicesInUserAgentString[k]) !== -1) {48 return true49 }50 }51 return false52 })();53 c.hasGestures = c.jGestures.data.hasGestures;54 c.jGestures.events = {55 touchstart: "jGestures.touchstart",56 touchendStart: "jGestures.touchend;start",57 touchendProcessed: "jGestures.touchend;processed",58 gesturestart: "jGestures.gesturestart",59 gestureendStart: "jGestures.gestureend;start",60 gestureendProcessed: "jGestures.gestureend;processed"61 };62 jQuery.each({63 orientationchange_orientationchange01: "orientationchange",64 gestureend_pinchopen01: "pinchopen",65 gestureend_pinchclose01: "pinchclose",66 gestureend_rotatecw01: "rotatecw",67 gestureend_rotateccw01: "rotateccw",68 gesturechange_pinch01: "pinch",69 gesturechange_rotate01: "rotate",70 touchstart_swipe13: "swipemove",71 touchstart_swipe01: "swipeone",72 touchstart_swipe02: "swipetwo",73 touchstart_swipe03: "swipethree",74 touchstart_swipe04: "swipefour",75 touchstart_swipe05: "swipeup",76 touchstart_swipe06: "swiperightup",77 touchstart_swipe07: "swiperight",78 touchstart_swipe08: "swiperightdown",79 touchstart_swipe09: "swipedown",80 touchstart_swipe10: "swipeleftdown",81 touchstart_swipe11: "swipeleft",82 touchstart_swipe12: "swipeleftup",83 touchstart_tap01: "tapone",84 touchstart_tap02: "taptwo",85 touchstart_tap03: "tapthree",86 touchstart_tap04: "tapfour",87 devicemotion_shake01: "shake",88 devicemotion_shake02: "shakefrontback",89 devicemotion_shake03: "shakeleftright",90 devicemotion_shake04: "shakeupdown"91 },92 function(l, k) {93 jQuery.event.special[k] = {94 setup: function() {95 var r = l.split("_");96 var o = r[0];97 var m = r[1].slice(0, r[1].length - 2);98 var p = jQuery(this);99 var q;100 var n;101 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {102 q = p.data("ojQueryGestures") || {};103 n = {};104 n[o] = true;105 c.extend(true, q, n);106 p.data("ojQueryGestures", q);107 if (c.hasGestures) {108 switch (m) {109 case "orientationchange":110 p.get(0).addEventListener("orientationchange", a, false);111 break;112 case "shake":113 case "shakefrontback":114 case "shakeleftright":115 case "shakeupdown":116 case "tilt":117 p.get(0).addEventListener("devicemotion", b, false);118 break;119 case "tap":120 case "swipe":121 case "swipeup":122 case "swiperightup":123 case "swiperight":124 case "swiperightdown":125 case "swipedown":126 case "swipeleftdown":127 case "swipeleft":128 p.get(0).addEventListener("touchstart", h, false);129 break;130 case "pinchopen":131 case "pinchclose":132 case "rotatecw":133 case "rotateccw":134 p.get(0).addEventListener("gesturestart", e, false);135 p.get(0).addEventListener("gestureend", i, false);136 break;137 case "pinch":138 case "rotate":139 p.get(0).addEventListener("gesturestart", e, false);140 p.get(0).addEventListener("gesturechange", f, false);141 break142 }143 } else {144 switch (m) {145 case "tap":146 case "swipe":147 p.bind("mousedown", h);148 break;149 case "orientationchange":150 case "pinchopen":151 case "pinchclose":152 case "rotatecw":153 case "rotateccw":154 case "pinch":155 case "rotate":156 case "shake":157 case "tilt":158 break159 }160 }161 }162 return false163 },164 add: function(n) {165 var m = jQuery(this);166 var o = m.data("ojQueryGestures");167 o[n.type] = {168 originalType: n.type169 };170 return false171 },172 remove: function(n) {173 var m = jQuery(this);174 var o = m.data("ojQueryGestures");175 o[n.type] = false;176 m.data("ojQueryGestures", o);177 return false178 },179 teardown: function() {180 var r = l.split("_");181 var o = r[0];182 var m = r[1].slice(0, r[1].length - 2);183 var p = jQuery(this);184 var q;185 var n;186 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {187 q = p.data("ojQueryGestures") || {};188 n = {};189 n[o] = false;190 c.extend(true, q, n);191 p.data("ojQueryGestures", q);192 if (c.hasGestures) {193 switch (m) {194 case "orientationchange":195 p.get(0).removeEventListener("orientationchange", a, false);196 break;197 case "shake":198 case "shakefrontback":199 case "shakeleftright":200 case "shakeupdown":201 case "tilt":202 p.get(0).removeEventListener("devicemotion", b, false);203 break;204 case "tap":205 case "swipe":206 case "swipeup":207 case "swiperightup":208 case "swiperight":209 case "swiperightdown":210 case "swipedown":211 case "swipeleftdown":212 case "swipeleft":213 case "swipeleftup":214 p.get(0).removeEventListener("touchstart", h, false);215 p.get(0).removeEventListener("touchmove", g, false);216 p.get(0).removeEventListener("touchend", j, false);217 break;218 case "pinchopen":219 case "pinchclose":220 case "rotatecw":221 case "rotateccw":222 p.get(0).removeEventListener("gesturestart", e, false);223 p.get(0).removeEventListener("gestureend", i, false);224 break;225 case "pinch":226 case "rotate":227 p.get(0).removeEventListener("gesturestart", e, false);228 p.get(0).removeEventListener("gesturechange", f, false);229 break230 }231 } else {232 switch (m) {233 case "tap":234 case "swipe":235 p.unbind("mousedown", h);236 p.unbind("mousemove", g);237 p.unbind("mouseup", j);238 break;239 case "orientationchange":240 case "pinchopen":241 case "pinchclose":242 case "rotatecw":243 case "rotateccw":244 case "pinch":245 case "rotate":246 case "shake":247 case "tilt":248 break249 }250 }251 }252 return false253 }254 }255 });256 function d(k) {257 k.startMove = (k.startMove) ? k.startMove: {258 startX: null,259 startY: null,260 timestamp: null261 };262 var l = new Date().getTime();263 var m;264 var n;265 if (k.touches) {266 n = [{267 lastX: k.deltaX,268 lastY: k.deltaY,269 moved: null,270 startX: k.screenX - k.startMove.screenX,271 startY: k.screenY - k.startMove.screenY272 }];273 m = {274 vector: k.vector || null,275 orientation: window.orientation || null,276 lastX: ((n[0].lastX > 0) ? +1 : ((n[0].lastX < 0) ? -1 : 0)),277 lastY: ((n[0].lastY > 0) ? +1 : ((n[0].lastY < 0) ? -1 : 0)),278 startX: ((n[0].startX > 0) ? +1 : ((n[0].startX < 0) ? -1 : 0)),279 startY: ((n[0].startY > 0) ? +1 : ((n[0].startY < 0) ? -1 : 0))280 };281 n[0].moved = Math.sqrt(Math.pow(Math.abs(n[0].startX), 2) + Math.pow(Math.abs(n[0].startY), 2))282 }283 return {284 type: k.type || null,285 originalEvent: k.event || null,286 delta: n || null,287 direction: m || {288 orientation: window.orientation || null,289 vector: k.vector || null290 },291 duration: (k.duration) ? k.duration: (k.startMove.timestamp) ? l - k.timestamp: null,292 rotation: k.rotation || null,293 scale: k.scale || null,294 description: k.description || [k.type, ":", k.touches, ":", ((n[0].lastX != 0) ? ((n[0].lastX > 0) ? "right": "left") : "steady"), ":", ((n[0].lastY != 0) ? ((n[0].lastY > 0) ? "down": "up") : "steady")].join("")295 }296 }297 function a(l) {298 var k = ["landscape:clockwise:", "portrait:default:", "landscape:counterclockwise:", "portrait:upsidedown:"];299 c(window).triggerHandler("orientationchange", {300 direction: {301 orientation: window.orientation302 },303 description: ["orientationchange:", k[((window.orientation / 90) + 1)], window.orientation].join("")304 })305 }306 function b(r) {307 var k;308 var t = jQuery(window);309 var o = t.data("ojQueryGestures");310 var m = c.jGestures.defaults.thresholdShake;311 var n = o.oDeviceMotionLastDevicePosition || {312 accelerationIncludingGravity: {313 x: 0,314 y: 0,315 z: 0316 },317 shake: {318 eventCount: 0,319 intervalsPassed: 0,320 intervalsFreeze: 0321 },322 shakeleftright: {323 eventCount: 0,324 intervalsPassed: 0,325 intervalsFreeze: 0326 },327 shakefrontback: {328 eventCount: 0,329 intervalsPassed: 0,330 intervalsFreeze: 0331 },332 shakeupdown: {333 eventCount: 0,334 intervalsPassed: 0,335 intervalsFreeze: 0336 }337 };338 var q = {339 accelerationIncludingGravity: {340 x: r.accelerationIncludingGravity.x,341 y: r.accelerationIncludingGravity.y,342 z: r.accelerationIncludingGravity.z343 },344 shake: {345 eventCount: n.shake.eventCount,346 intervalsPassed: n.shake.intervalsPassed,347 intervalsFreeze: n.shake.intervalsFreeze348 },349 shakeleftright: {350 eventCount: n.shakeleftright.eventCount,351 intervalsPassed: n.shakeleftright.intervalsPassed,352 intervalsFreeze: n.shakeleftright.intervalsFreeze353 },354 shakefrontback: {355 eventCount: n.shakefrontback.eventCount,356 intervalsPassed: n.shakefrontback.intervalsPassed,357 intervalsFreeze: n.shakefrontback.intervalsFreeze358 },359 shakeupdown: {360 eventCount: n.shakeupdown.eventCount,361 intervalsPassed: n.shakeupdown.intervalsPassed,362 intervalsFreeze: n.shakeupdown.intervalsFreeze363 }364 };365 var p;366 var s;367 var l;368 for (k in o) {369 switch (k) {370 case "shake":371 case "shakeleftright":372 case "shakefrontback":373 case "shakeupdown":374 p = [];375 s = [];376 p.push(k);377 if (++q[k].intervalsFreeze > m.freezeShakes && q[k].intervalsFreeze < (2 * m.freezeShakes)) {378 break379 }380 q[k].intervalsFreeze = 0;381 q[k].intervalsPassed++;382 if ((k === "shake" || k === "shakeleftright") && (q.accelerationIncludingGravity.x > m.leftright.sensitivity || q.accelerationIncludingGravity.x < ( - 1 * m.leftright.sensitivity))) {383 p.push("leftright");384 p.push("x-axis")385 }386 if ((k === "shake" || k === "shakefrontback") && (q.accelerationIncludingGravity.y > m.frontback.sensitivity || q.accelerationIncludingGravity.y < ( - 1 * m.frontback.sensitivity))) {387 p.push("frontback");388 p.push("y-axis")389 }390 if ((k === "shake" || k === "shakeupdown") && (q.accelerationIncludingGravity.z + 9.81 > m.updown.sensitivity || q.accelerationIncludingGravity.z + 9.81 < ( - 1 * m.updown.sensitivity))) {391 p.push("updown");392 p.push("z-axis")393 }394 if (p.length > 1) {395 if (++q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) < m.freezeShakes) {396 t.triggerHandler(k, d({397 type: k,398 description: p.join(":"),399 event: r,400 duration: q[k].intervalsPassed * 5401 }));402 q[k].eventCount = 0;403 q[k].intervalsPassed = 0;404 q[k].intervalsFreeze = m.freezeShakes + 1405 } else {406 if (q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) > m.freezeShakes) {407 q[k].eventCount = 0;408 q[k].intervalsPassed = 0409 }410 }411 }412 break413 }414 l = {};415 l.oDeviceMotionLastDevicePosition = q;416 t.data("ojQueryGestures", c.extend(true, o, l))417 }418 }419 function h(l) {420 var k = jQuery(l.currentTarget);421 k.triggerHandler(c.jGestures.events.touchstart, l);422 if (c.hasGestures) {423 l.currentTarget.addEventListener("touchmove", g, false);424 l.currentTarget.addEventListener("touchend", j, false)425 } else {426 k.bind("mousemove", g);427 k.bind("mouseup", j)428 }429 var n = k.data("ojQueryGestures");430 var m = (l.touches) ? l.touches[0] : l;431 var o = {};432 o.oLastSwipemove = {433 screenX: m.screenX,434 screenY: m.screenY,435 timestamp: new Date().getTime()436 };437 o.oStartTouch = {438 screenX: m.screenX,439 screenY: m.screenY,440 timestamp: new Date().getTime()441 };442 k.data("ojQueryGestures", c.extend(true, n, o))443 }444 function g(t) {445 var v = jQuery(t.currentTarget);446 var s = v.data("ojQueryGestures");447 var q = !!t.touches;448 var l = (q) ? t.changedTouches[0].screenX: t.screenX;449 var k = (q) ? t.changedTouches[0].screenY: t.screenY;450 var r = s.oLastSwipemove;451 var o = l - r.screenX;452 var n = k - r.screenY;453 var u;454 if ( !! s.oLastSwipemove) {455 u = d({456 type: "swipemove",457 touches: (q) ? t.touches.length: "1",458 screenY: k,459 screenX: l,460 deltaY: n,461 deltaX: o,462 startMove: r,463 event: t,464 timestamp: r.timestamp465 });466 v.triggerHandler(u.type, u)467 }468 var m = {};469 var p = (t.touches) ? t.touches[0] : t;470 m.oLastSwipemove = {471 screenX: p.screenX,472 screenY: p.screenY,473 timestamp: new Date().getTime()474 };475 v.data("ojQueryGestures", c.extend(true, s, m))476 }477 function j(r) {478 var v = jQuery(r.currentTarget);479 var x = !!r.changedTouches;480 var u = (x) ? r.changedTouches.length: "1";481 var p = (x) ? r.changedTouches[0].screenX: r.screenX;482 var o = (x) ? r.changedTouches[0].screenY: r.screenY;483 v.triggerHandler(c.jGestures.events.touchendStart, r);484 if (c.hasGestures) {485 r.currentTarget.removeEventListener("touchmove", g, false);486 r.currentTarget.removeEventListener("touchend", j, false)487 } else {488 v.unbind("mousemove", g);489 v.unbind("mouseup", j)490 }491 var m = v.data("ojQueryGestures");492 var y = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdMove || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdMove) ? true: false;493 var B = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdSwipe || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdSwipe) ? true: false;494 var A;495 var t;496 var n;497 var l;498 var k;499 var q;500 var w = ["zero", "one", "two", "three", "four"];501 var s;502 for (A in m) {503 t = m.oStartTouch;504 n = {};505 p = (x) ? r.changedTouches[0].screenX: r.screenX;506 o = (x) ? r.changedTouches[0].screenY: r.screenY;507 l = p - t.screenX;508 k = o - t.screenY;509 q = d({510 type: "swipe",511 touches: u,512 screenY: o,513 screenX: p,514 deltaY: k,515 deltaX: l,516 startMove: t,517 event: r,518 timestamp: t.timestamp519 });520 s = false;521 switch (A) {522 case "swipeone":523 if (x === false && u == 1 && y === false) {524 break525 }526 if (x === false || (u == 1 && y === true && B === true)) {527 s = true;528 q.type = ["swipe", w[u]].join("");529 v.triggerHandler(q.type, q)530 }531 break;532 case "swipetwo":533 if ((x && u == 2 && y === true && B === true)) {534 s = true;535 q.type = ["swipe", w[u]].join("");536 v.triggerHandler(q.type, q)537 }538 break;539 case "swipethree":540 if ((x && u == 3 && y === true && B === true)) {541 s = true;542 q.type = ["swipe", w[u]].join("");543 v.triggerHandler(q.type, q)544 }545 break;546 case "swipefour":547 if ((x && u == 4 && y === true && B === true)) {548 s = true;549 q.type = ["swipe", w[u]].join("");550 v.triggerHandler(q.type, q)551 }552 break;553 case "swipeup":554 case "swiperightup":555 case "swiperight":556 case "swiperightdown":557 case "swipedown":558 case "swipeleftdown":559 case "swipeleft":560 case "swipeleftup":561 if (x && y === true && B === true) {562 s = true;563 q.type = ["swipe", ((q.delta[0].lastX != 0) ? ((q.delta[0].lastX > 0) ? "right": "left") : ""), ((q.delta[0].lastY != 0) ? ((q.delta[0].lastY > 0) ? "down": "up") : "")].join("");564 v.triggerHandler(q.type, q)565 }566 break;567 case "tapone":568 case "taptwo":569 case "tapthree":570 case "tapfour":571 if ((y !== true && s !== true) && (w[u] == A.slice(3))) {572 q.description = ["tap", w[u]].join("");573 q.type = ["tap", w[u]].join("");574 v.triggerHandler(q.type, q)575 }576 break577 }578 var z = {};579 v.data("ojQueryGestures", c.extend(true, m, z));580 v.data("ojQueryGestures", c.extend(true, m, z))581 }582 v.triggerHandler(c.jGestures.events.touchendProcessed, r)583 }584 function e(l) {585 var k = jQuery(l.currentTarget);586 k.triggerHandler(c.jGestures.events.gesturestart, l);587 var m = k.data("ojQueryGestures");588 var n = {};589 n.oStartTouch = {590 timestamp: new Date().getTime()591 };592 k.data("ojQueryGestures", c.extend(true, m, n))593 }594 function f(l) {595 var k = jQuery(l.currentTarget);596 var p, m, r, o;597 var q = k.data("ojQueryGestures");598 var n;599 for (n in q) {600 switch (n) {601 case "pinch":602 p = l.scale;603 if (((p < 1) && (p % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) || ((p > 1) && (p % 1) > (c.jGestures.defaults.thresholdPinchopen))) {604 m = (p < 1) ? -1 : +1;605 o = d({606 type: "pinch",607 scale: p,608 touches: null,609 startMove: q.oStartTouch,610 event: l,611 timestamp: q.oStartTouch.timestamp,612 vector: m,613 description: ["pinch:", m, ":", ((p < 1) ? "close": "open")].join("")614 });615 k.triggerHandler(o.type, o)616 }617 break;618 case "rotate":619 p = l.rotation;620 if (((p < 1) && ( - 1 * (p) > c.jGestures.defaults.thresholdRotateccw)) || ((p > 1) && (p > c.jGestures.defaults.thresholdRotatecw))) {621 m = (p < 1) ? -1 : +1;622 o = d({623 type: "rotate",624 rotation: p,625 touches: null,626 startMove: q.oStartTouch,627 event: l,628 timestamp: q.oStartTouch.timestamp,629 vector: m,630 description: ["rotate:", m, ":", ((p < 1) ? "counterclockwise": "clockwise")].join("")631 });632 k.triggerHandler(o.type, o)633 }634 break635 }636 }637 }638 function i(l) {639 var k = jQuery(l.currentTarget);640 k.triggerHandler(c.jGestures.events.gestureendStart, l);641 var n;642 var o = k.data("ojQueryGestures");643 var m;644 for (m in o) {645 switch (m) {646 case "pinchclose":647 n = l.scale;648 if ((n < 1) && (n % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) {649 k.triggerHandler("pinchclose", d({650 type: "pinchclose",651 scale: n,652 vector: -1,653 touches: null,654 startMove: o.oStartTouch,655 event: l,656 timestamp: o.oStartTouch.timestamp,657 description: "pinch:-1:close"658 }))659 }660 break;661 case "pinchopen":662 n = l.scale;663 if ((n > 1) && (n % 1) > (c.jGestures.defaults.thresholdPinchopen)) {664 k.triggerHandler("pinchopen", d({665 type: "pinchopen",666 scale: n,667 vector: +1,668 touches: null,669 startMove: o.oStartTouch,670 event: l,671 timestamp: o.oStartTouch.timestamp,672 description: "pinch:+1:open"673 }))674 }675 break;676 case "rotatecw":677 n = l.rotation;678 if ((n > 1) && (n > c.jGestures.defaults.thresholdRotatecw)) {679 k.triggerHandler("rotatecw", d({680 type: "rotatecw",681 rotation: n,682 vector: +1,683 touches: null,684 startMove: o.oStartTouch,685 event: l,686 timestamp: o.oStartTouch.timestamp,687 description: "rotate:+1:clockwise"688 }))689 }690 break;691 case "rotateccw":692 n = l.rotation;693 if ((n < 1) && ( - 1 * (n) > c.jGestures.defaults.thresholdRotateccw)) {694 k.triggerHandler("rotateccw", d({695 type: "rotateccw",696 rotation: n,697 vector: -1,698 touches: null,699 startMove: o.oStartTouch,700 event: l,701 timestamp: o.oStartTouch.timestamp,702 description: "rotate:-1:counterclockwise"703 }))704 }705 break706 }707 }708 k.triggerHandler(c.jGestures.events.gestureendProcessed, l)709 }...
jgestures.min.js
Source:jgestures.min.js
1/**2 * jGestures: a jQuery plugin for gesture events3 * Copyright 2010-2011 Neue Digitale / Razorfish GmbH4 * Copyright 2011-2012, Razorfish GmbH5 * Licensed under the Apache License, Version 2.0 (the "License");6 * you may not use this file except in compliance with the License.7 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.08 * Unless required by applicable law or agreed to in writing, software9 * distributed under the License is distributed on an "AS IS" BASIS,10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11 * See the License for the specific language governing permissions and12 * limitations under the License.13 * @copyright Razorfish GmbH14 * @author martin.krause@razorfish.de15 * @version 0.90-shake16 * @requires jQuery JavaScript Library v1.4.2 - http://jquery.com/- Copyright 2010, John Resig- Dual licensed under the MIT or GPL Version 2 licenses. http://jquery.org/license17 */18(function(c) {19 c.jGestures = {};20 c.jGestures.defaults = {};21 c.jGestures.defaults.thresholdShake = { requiredShakes: 10, freezeShakes: 100, frontback: { sensitivity: 10 }, leftright: { sensitivity: 10 }, updown: { sensitivity: 10 } };22 c.jGestures.defaults.thresholdPinchopen = 0.05;23 c.jGestures.defaults.thresholdPinchmove = 0.05;24 c.jGestures.defaults.thresholdPinch = 0.05;25 c.jGestures.defaults.thresholdPinchclose = 0.05;26 c.jGestures.defaults.thresholdRotatecw = 5;27 c.jGestures.defaults.thresholdRotateccw = 5;28 c.jGestures.defaults.thresholdMove = 20;29 c.jGestures.defaults.thresholdSwipe = 100;30 c.jGestures.data = {};31 c.jGestures.data.capableDevicesInUserAgentString = ["iPad", "iPhone", "iPod", "Mobile Safari"];32 c.jGestures.data.hasGestures = (function() { var k; for (k = 0; k < c.jGestures.data.capableDevicesInUserAgentString.length; k++) { if (navigator.userAgent.indexOf(c.jGestures.data.capableDevicesInUserAgentString[k]) !== -1) { return true } } return false })();33 c.hasGestures = c.jGestures.data.hasGestures;34 c.jGestures.events = { touchstart: "jGestures.touchstart", touchendStart: "jGestures.touchend;start", touchendProcessed: "jGestures.touchend;processed", gesturestart: "jGestures.gesturestart", gestureendStart: "jGestures.gestureend;start", gestureendProcessed: "jGestures.gestureend;processed" };35 jQuery.each({ orientationchange_orientationchange01: "orientationchange", gestureend_pinchopen01: "pinchopen", gestureend_pinchclose01: "pinchclose", gestureend_rotatecw01: "rotatecw", gestureend_rotateccw01: "rotateccw", gesturechange_pinch01: "pinch", gesturechange_rotate01: "rotate", touchstart_swipe13: "swipemove", touchstart_swipe01: "swipeone", touchstart_swipe02: "swipetwo", touchstart_swipe03: "swipethree", touchstart_swipe04: "swipefour", touchstart_swipe05: "swipeup", touchstart_swipe06: "swiperightup", touchstart_swipe07: "swiperight", touchstart_swipe08: "swiperightdown", touchstart_swipe09: "swipedown", touchstart_swipe10: "swipeleftdown", touchstart_swipe11: "swipeleft", touchstart_swipe12: "swipeleftup", touchstart_tap01: "tapone", touchstart_tap02: "taptwo", touchstart_tap03: "tapthree", touchstart_tap04: "tapfour", devicemotion_shake01: "shake", devicemotion_shake02: "shakefrontback", devicemotion_shake03: "shakeleftright", devicemotion_shake04: "shakeupdown" }, function(l, k) {36 jQuery.event.special[k] = {37 setup: function() {38 var r = l.split("_");39 var o = r[0];40 var m = r[1].slice(0, r[1].length - 2);41 var p = jQuery(this);42 var q;43 var n;44 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {45 q = p.data("ojQueryGestures") || {};46 n = {};47 n[o] = true;48 c.extend(true, q, n);49 p.data("ojQueryGestures", q);50 if (c.hasGestures) {51 switch (m) {52 case "orientationchange":53 p.get(0).addEventListener("orientationchange", a, false);54 break;55 case "shake":56 case "shakefrontback":57 case "shakeleftright":58 case "shakeupdown":59 case "tilt":60 p.get(0).addEventListener("devicemotion", b, false);61 break;62 case "tap":63 case "swipe":64 case "swipeup":65 case "swiperightup":66 case "swiperight":67 case "swiperightdown":68 case "swipedown":69 case "swipeleftdown":70 case "swipeleft":71 p.get(0).addEventListener("touchstart", h, false);72 break;73 case "pinchopen":74 case "pinchclose":75 case "rotatecw":76 case "rotateccw":77 p.get(0).addEventListener("gesturestart", e, false);78 p.get(0).addEventListener("gestureend", i, false);79 break;80 case "pinch":81 case "rotate":82 p.get(0).addEventListener("gesturestart", e, false);83 p.get(0).addEventListener("gesturechange", f, false);84 break85 }86 } else {87 switch (m) {88 case "tap":89 case "swipe":90 p.bind("mousedown", h);91 break;92 case "orientationchange":93 case "pinchopen":94 case "pinchclose":95 case "rotatecw":96 case "rotateccw":97 case "pinch":98 case "rotate":99 case "shake":100 case "tilt":101 break102 }103 }104 }105 return false106 },107 add: function(n) {108 var m = jQuery(this);109 var o = m.data("ojQueryGestures");110 o[n.type] = { originalType: n.type };111 return false112 },113 remove: function(n) {114 var m = jQuery(this);115 var o = m.data("ojQueryGestures");116 o[n.type] = false;117 m.data("ojQueryGestures", o);118 return false119 },120 teardown: function() {121 var r = l.split("_");122 var o = r[0];123 var m = r[1].slice(0, r[1].length - 2);124 var p = jQuery(this);125 var q;126 var n;127 if (!p.data("ojQueryGestures") || !p.data("ojQueryGestures")[o]) {128 q = p.data("ojQueryGestures") || {};129 n = {};130 n[o] = false;131 c.extend(true, q, n);132 p.data("ojQueryGestures", q);133 if (c.hasGestures) {134 switch (m) {135 case "orientationchange":136 p.get(0).removeEventListener("orientationchange", a, false);137 break;138 case "shake":139 case "shakefrontback":140 case "shakeleftright":141 case "shakeupdown":142 case "tilt":143 p.get(0).removeEventListener("devicemotion", b, false);144 break;145 case "tap":146 case "swipe":147 case "swipeup":148 case "swiperightup":149 case "swiperight":150 case "swiperightdown":151 case "swipedown":152 case "swipeleftdown":153 case "swipeleft":154 case "swipeleftup":155 p.get(0).removeEventListener("touchstart", h, false);156 p.get(0).removeEventListener("touchmove", g, false);157 p.get(0).removeEventListener("touchend", j, false);158 break;159 case "pinchopen":160 case "pinchclose":161 case "rotatecw":162 case "rotateccw":163 p.get(0).removeEventListener("gesturestart", e, false);164 p.get(0).removeEventListener("gestureend", i, false);165 break;166 case "pinch":167 case "rotate":168 p.get(0).removeEventListener("gesturestart", e, false);169 p.get(0).removeEventListener("gesturechange", f, false);170 break171 }172 } else {173 switch (m) {174 case "tap":175 case "swipe":176 p.unbind("mousedown", h);177 p.unbind("mousemove", g);178 p.unbind("mouseup", j);179 break;180 case "orientationchange":181 case "pinchopen":182 case "pinchclose":183 case "rotatecw":184 case "rotateccw":185 case "pinch":186 case "rotate":187 case "shake":188 case "tilt":189 break190 }191 }192 }193 return false194 }195 }196 });197 function d(k) {198 k.startMove = (k.startMove) ? k.startMove : { startX: null, startY: null, timestamp: null };199 var l = new Date().getTime();200 var m;201 var n;202 if (k.touches) {203 n = [{ lastX: k.deltaX, lastY: k.deltaY, moved: null, startX: k.screenX - k.startMove.screenX, startY: k.screenY - k.startMove.screenY }];204 m = { vector: k.vector || null, orientation: window.orientation || null, lastX: ((n[0].lastX > 0) ? +1 : ((n[0].lastX < 0) ? -1 : 0)), lastY: ((n[0].lastY > 0) ? +1 : ((n[0].lastY < 0) ? -1 : 0)), startX: ((n[0].startX > 0) ? +1 : ((n[0].startX < 0) ? -1 : 0)), startY: ((n[0].startY > 0) ? +1 : ((n[0].startY < 0) ? -1 : 0)) };205 n[0].moved = Math.sqrt(Math.pow(Math.abs(n[0].startX), 2) + Math.pow(Math.abs(n[0].startY), 2))206 }207 return { type: k.type || null, originalEvent: k.event || null, delta: n || null, direction: m || { orientation: window.orientation || null, vector: k.vector || null }, duration: (k.duration) ? k.duration : (k.startMove.timestamp) ? l - k.timestamp : null, rotation: k.rotation || null, scale: k.scale || null, description: k.description || [k.type, ":", k.touches, ":", ((n[0].lastX != 0) ? ((n[0].lastX > 0) ? "right" : "left") : "steady"), ":", ((n[0].lastY != 0) ? ((n[0].lastY > 0) ? "down" : "up") : "steady")].join("") }208 }209 function a(l) {210 var k = ["landscape:clockwise:", "portrait:default:", "landscape:counterclockwise:", "portrait:upsidedown:"];211 c(window).triggerHandler("orientationchange", { direction: { orientation: window.orientation }, description: ["orientationchange:", k[((window.orientation / 90) + 1)], window.orientation].join("") })212 }213 function b(r) {214 var k;215 var t = jQuery(window);216 var o = t.data("ojQueryGestures");217 var m = c.jGestures.defaults.thresholdShake;218 var n = o.oDeviceMotionLastDevicePosition || { accelerationIncludingGravity: { x: 0, y: 0, z: 0 }, shake: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 }, shakeleftright: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 }, shakefrontback: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 }, shakeupdown: { eventCount: 0, intervalsPassed: 0, intervalsFreeze: 0 } };219 var q = { accelerationIncludingGravity: { x: r.accelerationIncludingGravity.x, y: r.accelerationIncludingGravity.y, z: r.accelerationIncludingGravity.z }, shake: { eventCount: n.shake.eventCount, intervalsPassed: n.shake.intervalsPassed, intervalsFreeze: n.shake.intervalsFreeze }, shakeleftright: { eventCount: n.shakeleftright.eventCount, intervalsPassed: n.shakeleftright.intervalsPassed, intervalsFreeze: n.shakeleftright.intervalsFreeze }, shakefrontback: { eventCount: n.shakefrontback.eventCount, intervalsPassed: n.shakefrontback.intervalsPassed, intervalsFreeze: n.shakefrontback.intervalsFreeze }, shakeupdown: { eventCount: n.shakeupdown.eventCount, intervalsPassed: n.shakeupdown.intervalsPassed, intervalsFreeze: n.shakeupdown.intervalsFreeze } };220 var p;221 var s;222 var l;223 for (k in o) {224 switch (k) {225 case "shake":226 case "shakeleftright":227 case "shakefrontback":228 case "shakeupdown":229 p = [];230 s = [];231 p.push(k);232 if (++q[k].intervalsFreeze > m.freezeShakes && q[k].intervalsFreeze < (2 * m.freezeShakes)) { break }233 q[k].intervalsFreeze = 0;234 q[k].intervalsPassed++;235 if ((k === "shake" || k === "shakeleftright") && (q.accelerationIncludingGravity.x > m.leftright.sensitivity || q.accelerationIncludingGravity.x < (-1 * m.leftright.sensitivity))) {236 p.push("leftright");237 p.push("x-axis")238 }239 if ((k === "shake" || k === "shakefrontback") && (q.accelerationIncludingGravity.y > m.frontback.sensitivity || q.accelerationIncludingGravity.y < (-1 * m.frontback.sensitivity))) {240 p.push("frontback");241 p.push("y-axis")242 }243 if ((k === "shake" || k === "shakeupdown") && (q.accelerationIncludingGravity.z + 9.81 > m.updown.sensitivity || q.accelerationIncludingGravity.z + 9.81 < (-1 * m.updown.sensitivity))) {244 p.push("updown");245 p.push("z-axis")246 }247 if (p.length > 1) {248 if (++q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) < m.freezeShakes) {249 t.triggerHandler(k, d({ type: k, description: p.join(":"), event: r, duration: q[k].intervalsPassed * 5 }));250 q[k].eventCount = 0;251 q[k].intervalsPassed = 0;252 q[k].intervalsFreeze = m.freezeShakes + 1253 } else {254 if (q[k].eventCount == m.requiredShakes && (q[k].intervalsPassed) > m.freezeShakes) {255 q[k].eventCount = 0;256 q[k].intervalsPassed = 0257 }258 }259 }260 break261 }262 l = {};263 l.oDeviceMotionLastDevicePosition = q;264 t.data("ojQueryGestures", c.extend(true, o, l))265 }266 }267 function h(l) {268 var k = jQuery(l.currentTarget);269 k.triggerHandler(c.jGestures.events.touchstart, l);270 if (c.hasGestures) {271 l.currentTarget.addEventListener("touchmove", g, false);272 l.currentTarget.addEventListener("touchend", j, false)273 } else {274 k.bind("mousemove", g);275 k.bind("mouseup", j)276 }277 var n = k.data("ojQueryGestures");278 var m = (l.touches) ? l.touches[0] : l;279 var o = {};280 o.oLastSwipemove = { screenX: m.screenX, screenY: m.screenY, timestamp: new Date().getTime() };281 o.oStartTouch = { screenX: m.screenX, screenY: m.screenY, timestamp: new Date().getTime() };282 k.data("ojQueryGestures", c.extend(true, n, o))283 }284 function g(t) {285 var v = jQuery(t.currentTarget);286 var s = v.data("ojQueryGestures");287 var q = !!t.touches;288 var l = (q) ? t.changedTouches[0].screenX : t.screenX;289 var k = (q) ? t.changedTouches[0].screenY : t.screenY;290 var r = s.oLastSwipemove;291 var o = l - r.screenX;292 var n = k - r.screenY;293 var u;294 if (!!s.oLastSwipemove) {295 u = d({ type: "swipemove", touches: (q) ? t.touches.length : "1", screenY: k, screenX: l, deltaY: n, deltaX: o, startMove: r, event: t, timestamp: r.timestamp });296 v.triggerHandler(u.type, u)297 }298 var m = {};299 var p = (t.touches) ? t.touches[0] : t;300 m.oLastSwipemove = { screenX: p.screenX, screenY: p.screenY, timestamp: new Date().getTime() };301 v.data("ojQueryGestures", c.extend(true, s, m))302 }303 function j(r) {304 var v = jQuery(r.currentTarget);305 var x = !!r.changedTouches;306 var u = (x) ? r.changedTouches.length : "1";307 var p = (x) ? r.changedTouches[0].screenX : r.screenX;308 var o = (x) ? r.changedTouches[0].screenY : r.screenY;309 v.triggerHandler(c.jGestures.events.touchendStart, r);310 if (c.hasGestures) {311 r.currentTarget.removeEventListener("touchmove", g, false);312 r.currentTarget.removeEventListener("touchend", j, false)313 } else {314 v.unbind("mousemove", g);315 v.unbind("mouseup", j)316 }317 var m = v.data("ojQueryGestures");318 var y = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdMove || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdMove) ? true : false;319 var B = (Math.abs(m.oStartTouch.screenX - p) > c.jGestures.defaults.thresholdSwipe || Math.abs(m.oStartTouch.screenY - o) > c.jGestures.defaults.thresholdSwipe) ? true : false;320 var A;321 var t;322 var n;323 var l;324 var k;325 var q;326 var w = ["zero", "one", "two", "three", "four"];327 var s;328 for (A in m) {329 t = m.oStartTouch;330 n = {};331 p = (x) ? r.changedTouches[0].screenX : r.screenX;332 o = (x) ? r.changedTouches[0].screenY : r.screenY;333 l = p - t.screenX;334 k = o - t.screenY;335 q = d({ type: "swipe", touches: u, screenY: o, screenX: p, deltaY: k, deltaX: l, startMove: t, event: r, timestamp: t.timestamp });336 s = false;337 switch (A) {338 case "swipeone":339 if (x === false && u == 1 && y === false) { break }340 if (x === false || (u == 1 && y === true && B === true)) {341 s = true;342 q.type = ["swipe", w[u]].join("");343 v.triggerHandler(q.type, q)344 }345 break;346 case "swipetwo":347 if ((x && u == 2 && y === true && B === true)) {348 s = true;349 q.type = ["swipe", w[u]].join("");350 v.triggerHandler(q.type, q)351 }352 break;353 case "swipethree":354 if ((x && u == 3 && y === true && B === true)) {355 s = true;356 q.type = ["swipe", w[u]].join("");357 v.triggerHandler(q.type, q)358 }359 break;360 case "swipefour":361 if ((x && u == 4 && y === true && B === true)) {362 s = true;363 q.type = ["swipe", w[u]].join("");364 v.triggerHandler(q.type, q)365 }366 break;367 case "swipeup":368 case "swiperightup":369 case "swiperight":370 case "swiperightdown":371 case "swipedown":372 case "swipeleftdown":373 case "swipeleft":374 case "swipeleftup":375 if (x && y === true && B === true) {376 s = true;377 q.type = ["swipe", ((q.delta[0].lastX != 0) ? ((q.delta[0].lastX > 0) ? "right" : "left") : ""), ((q.delta[0].lastY != 0) ? ((q.delta[0].lastY > 0) ? "down" : "up") : "")].join("");378 v.triggerHandler(q.type, q)379 }380 break;381 case "tapone":382 case "taptwo":383 case "tapthree":384 case "tapfour":385 if ((y !== true && s !== true) && (w[u] == A.slice(3))) {386 q.description = ["tap", w[u]].join("");387 q.type = ["tap", w[u]].join("");388 v.triggerHandler(q.type, q)389 }390 break391 }392 var z = {};393 v.data("ojQueryGestures", c.extend(true, m, z));394 v.data("ojQueryGestures", c.extend(true, m, z))395 }396 v.triggerHandler(c.jGestures.events.touchendProcessed, r)397 }398 function e(l) {399 var k = jQuery(l.currentTarget);400 k.triggerHandler(c.jGestures.events.gesturestart, l);401 var m = k.data("ojQueryGestures");402 var n = {};403 n.oStartTouch = { timestamp: new Date().getTime() };404 k.data("ojQueryGestures", c.extend(true, m, n))405 }406 function f(l) {407 var k = jQuery(l.currentTarget);408 var p, m, r, o;409 var q = k.data("ojQueryGestures");410 var n;411 for (n in q) {412 switch (n) {413 case "pinch":414 p = l.scale;415 if (((p < 1) && (p % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) || ((p > 1) && (p % 1) > (c.jGestures.defaults.thresholdPinchopen))) {416 m = (p < 1) ? -1 : +1;417 o = d({ type: "pinch", scale: p, touches: null, startMove: q.oStartTouch, event: l, timestamp: q.oStartTouch.timestamp, vector: m, description: ["pinch:", m, ":", ((p < 1) ? "close" : "open")].join("") });418 k.triggerHandler(o.type, o)419 }420 break;421 case "rotate":422 p = l.rotation;423 if (((p < 1) && (-1 * (p) > c.jGestures.defaults.thresholdRotateccw)) || ((p > 1) && (p > c.jGestures.defaults.thresholdRotatecw))) {424 m = (p < 1) ? -1 : +1;425 o = d({ type: "rotate", rotation: p, touches: null, startMove: q.oStartTouch, event: l, timestamp: q.oStartTouch.timestamp, vector: m, description: ["rotate:", m, ":", ((p < 1) ? "counterclockwise" : "clockwise")].join("") });426 k.triggerHandler(o.type, o)427 }428 break429 }430 }431 }432 function i(l) {433 var k = jQuery(l.currentTarget);434 k.triggerHandler(c.jGestures.events.gestureendStart, l);435 var n;436 var o = k.data("ojQueryGestures");437 var m;438 for (m in o) {439 switch (m) {440 case "pinchclose":441 n = l.scale;442 if ((n < 1) && (n % 1) < (1 - c.jGestures.defaults.thresholdPinchclose)) { k.triggerHandler("pinchclose", d({ type: "pinchclose", scale: n, vector: -1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "pinch:-1:close" })) }443 break;444 case "pinchopen":445 n = l.scale;446 if ((n > 1) && (n % 1) > (c.jGestures.defaults.thresholdPinchopen)) { k.triggerHandler("pinchopen", d({ type: "pinchopen", scale: n, vector: +1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "pinch:+1:open" })) }447 break;448 case "rotatecw":449 n = l.rotation;450 if ((n > 1) && (n > c.jGestures.defaults.thresholdRotatecw)) { k.triggerHandler("rotatecw", d({ type: "rotatecw", rotation: n, vector: +1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "rotate:+1:clockwise" })) }451 break;452 case "rotateccw":453 n = l.rotation;454 if ((n < 1) && (-1 * (n) > c.jGestures.defaults.thresholdRotateccw)) { k.triggerHandler("rotateccw", d({ type: "rotateccw", rotation: n, vector: -1, touches: null, startMove: o.oStartTouch, event: l, timestamp: o.oStartTouch.timestamp, description: "rotate:-1:counterclockwise" })) }455 break456 }457 }458 k.triggerHandler(c.jGestures.events.gestureendProcessed, l)459 }...
scripts-alt.js
Source:scripts-alt.js
1$(function() {2 mouseWheelIn();3 mouseWheelOut();4 pinchOpen();5 pinchClose();6 $(document).on("pagechange", function () {7 pinchOpen();8 });9 //$("a").unbind("mousewheel");10});11function mouseWheelIn () {12 var timeStamp = new Date().getTime();13 14 $(document).on("mousewheel", "[data-link='true']", function (event, delta, deltaX, deltaY) {15 event.preventDefault();16 17 var timeNow = new Date().getTime(),18 target = $(this).attr("data-target");19 if(timeNow - timeStamp < 100) {20 //console.log(timeNow - timeStamp + " = Too soon.");21 timeStamp = timeNow;...
scripts.js
Source:scripts.js
1$(function() {2 mouseWheelIn();3 mouseWheelOut();4 pinchOpen();5 pinchClose();6 $(document).on("pagechange", function () {7 pinchOpen();8 });9 //$("a").unbind("mousewheel");10});11function mouseWheelIn () {12 var timeStamp = new Date().getTime();13 14 $(document).on("mousewheel", "a", function (event, delta, deltaX, deltaY) {15 event.preventDefault();16 17 var timeNow = new Date().getTime(),18 target = $(this).attr("href");19 if(timeNow - timeStamp < 100) {20 //console.log(timeNow - timeStamp + " = Too soon.");21 timeStamp = timeNow;...
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 {20 timeStamp = timeNow;21 if (delta < 0) {...
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.pinchOpen();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.pinchOpen({ x: 100, y: 100 });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({ x: 100, y: 100 });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.pinchTo({ x: 100, y: 100 }, { x: 300, y: 300 });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.type('input[name="q"]', 'Playwright');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.press('input[name="q"]', 'Enter');39 await browser.close();40})();41const { chromium } = require('playwright');42(async () => {43 const browser = await chromium.launch();
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.pinchOpen();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();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.pinchTo({ x: 100, y: 100 }, { scale: 1.5 });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.screenshot();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.tap('input');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();46 await page.type('input', 'Playwright');47 await browser.close();48})();49const { chromium } = require('playwright');50(async () => {
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({ headless: false });4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.pinchOpen();7 await browser.close();8})();9const { chromium } = require('playwright');10(async () => {11 const browser = await chromium.launch({ headless: false });12 const context = await browser.newContext();13 const page = await context.newPage();14 await page.pinchClose();15 await browser.close();16})();17const { chromium } = require('playwright');18(async () => {19 const browser = await chromium.launch({ headless: false });20 const context = await browser.newContext();21 const page = await context.newPage();22 await page.pinchTo({ x: 100, y: 100 }, { scale: 2 });23 await browser.close();24})();25const { chromium } = require('playwright');26(async () => {27 const browser = await chromium.launch({ headless: false });28 const context = await browser.newContext();29 const page = await context.newPage();30 await page.touchscreen.tap(100, 100);31 await browser.close();32})();33const { chromium } = require('playwright');34(async () => {35 const browser = await chromium.launch({ headless: false });36 const context = await browser.newContext();37 const page = await context.newPage();38 await page.type('input[name="q"]', 'Hello World');39 await browser.close();40})();41const { chromium } = require('playwright');42(async () => {43 const browser = await chromium.launch({ headless: false });
Using AI Code Generation
1const { chromium, devices } = 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.pinchOpen({ x: 100, y: 100 });7 await page.screenshot({ path: 'pinchOpen.png' });8 await browser.close();9})();10Recommended Posts: Playwright | pinchClose() method11Playwright | pinchToZoom() method12Playwright | tap() method13Playwright | click() method14Playwright | type() method15Playwright | waitForSelector() method16Playwright | waitForFunction() method17Playwright | waitForRequest() method18Playwright | waitForResponse() method19Playwright | waitForNavigation() method20Playwright | waitForLoadState() method21Playwright | waitForFileChooser() method22Playwright | waitForEvent() method23Playwright | waitForTimeout() method24Playwright | waitForRequest() method25Playwright | waitForResponse() method26Playwright | waitForNavigation() method27Playwright | waitForLoadState() method28Playwright | waitForFileChooser() method29Playwright | waitForEvent() method30Playwright | waitForTimeout() method31Playwright | waitForRequest() method32Playwright | waitForResponse() method33Playwright | waitForNavigation() method34Playwright | waitForLoadState() method35Playwright | waitForFileChooser() method36Playwright | waitForEvent() method37Playwright | waitForTimeout() method38Playwright | waitForRequest() method39Playwright | waitForResponse() method40Playwright | waitForNavigation() method41Playwright | waitForLoadState() method42Playwright | waitForFileChooser() method43Playwright | waitForEvent() method44Playwright | waitForTimeout() method45Playwright | waitForRequest() method46Playwright | waitForResponse() method47Playwright | waitForNavigation() method48Playwright | waitForLoadState() method49Playwright | waitForFileChooser() method50Playwright | waitForEvent() method51Playwright | waitForTimeout() method52Playwright | waitForRequest() method53Playwright | waitForResponse() method54Playwright | waitForNavigation() method
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.pinchOpen();6 await browser.close();7})();8const { chromium } = require('playwright');9(async () => {10 const browser = await chromium.launch();11 const page = await browser.newPage();12 await page.pinchClose();13 await browser.close();14})();15const { chromium } = require('playwright');16(async () => {17 const browser = await chromium.launch();18 const page = await browser.newPage();19 await page.pinchTo({ x: 10, y: 10 }, { scale: 2 });20 await browser.close();21})();22const { chromium } = require('playwright');23(async () => {24 const browser = await chromium.launch();25 const page = await browser.newPage();26 await page.tap('input');27 await browser.close();28})();29const { chromium } = require('playwright');30(async () => {31 const browser = await chromium.launch();32 const page = await browser.newPage();33 await page.doubleTap('input');34 await browser.close();35})();36const { chromium } = require('playwright');37(async () => {38 const browser = await chromium.launch();39 const page = await browser.newPage();40 await page.tripleTap('input');41 await browser.close();42})();43const { chromium } = require('playwright');44(async () => {45 const browser = await chromium.launch();46 const page = await browser.newPage();
Using AI Code Generation
1const { devices } = require('playwright');2const iPhone = devices['iPhone 6'];3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext({6 geolocation: { longitude: 12.492507, latitude: 41.889938 },7 });8 const page = await context.newPage();9 await page.click('text="Your location"');10 await page.waitForTimeout(3000);
Using AI Code Generation
1const { devices } = require('playwright');2const iPhone11 = devices['iPhone 11 Pro'];3const {chromium} = require('playwright');4(async () => {5 const browser = await chromium.launch();6 const context = await browser.newContext({7 geolocation: { longitude: 12.492507, latitude: 41.889938 },8 });9 const page = await context.newPage();10 await page.click('text="Your location"');11 await page.click('#searchboxinput');12 await page.fill('#searchboxinput', 'Rome');13 await page.click('text="Rome, Italy"');14 await page.click('text="Rome, Italy"');15 await page.click('#searchboxinput');16 await page.fill('#searchboxinput', 'Milan');17 await page.click('text="Milan, Italy"');18 await page.click('text="Milan, Italy"');19 await page.click('#searchboxinput');20 await page.fill('#searchboxinput', 'Venice');21 await page.click('text="Venice, Italy"');22 await page.click('text="Venice, Italy"');23 await page.click('#searchboxinput');24 await page.fill('#searchboxinput', 'Florence');25 await page.click('text="Florence, Italy"');26 await page.click('text="Florence, Italy"');27 await page.click('#searchboxinput');28 await page.fill('#searchboxinput', 'Naples');29 await page.click('text="Naples, Italy"');30 await page.click('text="Naples, Italy"');31 await page.click('#searchboxinput');32 await page.fill('#searchboxinput', 'Bologna');33 await page.click('text="Bologna, Italy"');34 await page.click('text="Bologna, Italy"');35 await page.click('#searchboxinput');36 await page.fill('#searchboxinput', 'Turin');37 await page.click('text="Turin, Italy"');38 await page.click('text="Turin, Italy"');39 await page.click('#searchboxinput');40 await page.fill('#searchboxinput', 'Genoa');41 await page.click('text="Genoa
Using AI Code Generation
1const { pinchOpen } = require('playwright/lib/internal/remote');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await pinchOpen(page, { x: 100, y: 100 });8 await browser.close();9})();
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!!