| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>gestures_test.html</title> |
| <script src="test_bootstrap.js"></script> |
| <script type="text/javascript"> |
| goog.require('bot.action'); |
| goog.require('bot.userAgent'); |
| goog.require('goog.dom'); |
| goog.require('goog.events'); |
| goog.require('goog.events.EventType'); |
| goog.require('goog.testing.jsunit'); |
| goog.require('goog.userAgent.product'); |
| </script> |
| <script type="text/javascript"> |
| var elem, startCoords, firstMoveCoords, secondMoveCoords, endCoords; |
| |
| function setUp() { |
| elem = goog.dom.getElement('multitouch'); |
| goog.events.removeAll(elem); |
| startCoords = []; |
| firstMoveCoords = []; |
| secondMoveCoords = []; |
| endCoords = []; |
| |
| function handleCoords(event, touchListName) { |
| event.preventDefault(); |
| var e = event.getBrowserEvent(); |
| var touches = e[touchListName]; |
| assertEquals(2, touches.length); |
| var touch0 = touches[0], touch1 = touches[1]; |
| return [ |
| new goog.math.Coordinate(touch0.clientX, touch0.clientY), |
| new goog.math.Coordinate(touch1.clientX, touch1.clientY) |
| ]; |
| } |
| |
| goog.events.listen(elem, goog.events.EventType.TOUCHSTART, function(e) { |
| assert('touchstart already fired', !startCoords.length); |
| startCoords = handleCoords(e, 'touches'); |
| }); |
| |
| goog.events.listen(elem, goog.events.EventType.TOUCHMOVE, function(e) { |
| assert('two touchmoves already fired', !secondMoveCoords.length); |
| if (!firstMoveCoords.length) { |
| firstMoveCoords = handleCoords(e, 'touches'); |
| } else { |
| secondMoveCoords = handleCoords(e, 'touches'); |
| } |
| }); |
| |
| goog.events.listen(elem, goog.events.EventType.TOUCHEND, function(e) { |
| assert('touchend already fired', !endCoords.length); |
| endCoords = handleCoords(e, 'changedTouches'); |
| }); |
| |
| function handlePointerCoords(event) { |
| event.preventDefault(); |
| var e = event.getBrowserEvent(); |
| return new goog.math.Coordinate(e.clientX, e.clientY); |
| } |
| |
| goog.events.listen(elem, goog.events.EventType.MSPOINTERDOWN, |
| function(e) { |
| assert('MSPointerDown already fired', startCoords.length < 2); |
| startCoords.push(handlePointerCoords(e)); |
| }); |
| |
| goog.events.listen(elem, goog.events.EventType.MSPOINTERMOVE, |
| function(e) { |
| assert('MSPointerMoves already fired', secondMoveCoords.length < 2); |
| if (firstMoveCoords.length < 2) { |
| firstMoveCoords.push(handlePointerCoords(e)); |
| } else { |
| secondMoveCoords.push(handlePointerCoords(e)); |
| } |
| }); |
| |
| goog.events.listen(elem, goog.events.EventType.MSPOINTERUP, function(e) { |
| assert('MSPointerUp already fired', endCoords.length < 2); |
| endCoords.push(handlePointerCoords(e)); |
| }); |
| } |
| |
| var EPSILON = 0.01; |
| |
| function assertApproxEquals(comment, expected, actual) { |
| // Android 4+ coerces real numbered coordinates to their floor values. |
| if (goog.userAgent.product.ANDROID && |
| bot.userAgent.isProductVersion(4)) { |
| var expectedMinFloor = Math.floor(expected - EPSILON); |
| var expectedMaxFloor = Math.floor(expected + EPSILON); |
| assertTrue(actual >= expectedMinFloor); |
| assertTrue(actual <= expectedMaxFloor); |
| } else { |
| assertRoughlyEquals(comment, expected, actual, EPSILON); |
| } |
| } |
| |
| function assertMultitouchPoints(start0X, start0Y, start1X, start1Y, |
| mid0X, mid0Y, mid1X, mid1Y, end0X, end0Y, end1X, end1Y) { |
| assertApproxEquals('start 0 x', start0X, startCoords[0].x); |
| assertApproxEquals('start 0 y', start0Y, startCoords[0].y); |
| assertApproxEquals('start 1 x', start1X, startCoords[1].x); |
| assertApproxEquals('start 1 y', start1Y, startCoords[1].y); |
| |
| assertApproxEquals('first move 0 x', mid0X, firstMoveCoords[0].x); |
| assertApproxEquals('first move 0 y', mid0Y, firstMoveCoords[0].y); |
| assertApproxEquals('first move 1 x', mid1X, firstMoveCoords[1].x); |
| assertApproxEquals('first move 1 y', mid1Y, firstMoveCoords[1].y); |
| |
| assertApproxEquals('second move 0 x', end0X, secondMoveCoords[0].x); |
| assertApproxEquals('second move 0 y', end0Y, secondMoveCoords[0].y); |
| assertApproxEquals('second move 1 x', end1X, secondMoveCoords[1].x); |
| assertApproxEquals('second move 1 y', end1Y, secondMoveCoords[1].y); |
| |
| assertApproxEquals('end 0 x', end0X, endCoords[0].x); |
| assertApproxEquals('end 0 y', end0Y, endCoords[0].y); |
| assertApproxEquals('end 1 x', end1X, endCoords[1].x); |
| assertApproxEquals('end 1 y', end1Y, endCoords[1].y); |
| } |
| |
| function testPinchInward() { |
| if (!bot.events.SUPPORTS_TOUCH_EVENTS) { |
| return; |
| } |
| // We'll pinch the square element in half. |
| var pinchDistance = Math.sqrt(2 * 50 * 50) / 2; |
| bot.action.pinch(elem, pinchDistance); |
| assertMultitouchPoints(/* start */ 100, 100, 0, 0, |
| /* mid */ 87.5, 87.5, 12.5, 12.5, |
| /* end */ 75, 75, 25, 25); |
| } |
| |
| function testPinchOutward() { |
| if (!bot.events.SUPPORTS_TOUCH_EVENTS) { |
| return; |
| } |
| // We'll pinch the square element from the halfway point. |
| var pinchDistance = -Math.sqrt(2 * 50 * 50) / 2; |
| bot.action.pinch(elem, pinchDistance); |
| assertMultitouchPoints(/* start */ 75, 75, 25, 25, |
| /* mid */ 87.5, 87.5, 12.5, 12.5, |
| /* end */ 100, 100, 0, 0); |
| } |
| |
| function testRotateClockwise() { |
| if (!bot.events.SUPPORTS_TOUCH_EVENTS) { |
| return; |
| } |
| bot.action.rotate(elem, 90); |
| var midYOffset = Math.sqrt(2 * 25 * 25); |
| assertMultitouchPoints(/* start */ 75, 75, 25, 25, |
| /* mid */ 50, 50 + midYOffset, 50, 50 - midYOffset, |
| /* end */ 25, 75, 75, 25); |
| } |
| |
| function testRotateCounterClockwise() { |
| if (!bot.events.SUPPORTS_TOUCH_EVENTS) { |
| return; |
| } |
| bot.action.rotate(elem, -90); |
| var midXOffset = Math.sqrt(2 * 25 * 25); |
| assertMultitouchPoints(/* start */ 75, 75, 25, 25, |
| /* mid */ 50 + midXOffset, 50, 50 - midXOffset, 50, |
| /* end */ 75, 25, 25, 75); |
| } |
| </script> |
| </head> |
| <body> |
| <div id="multitouch" |
| style="position:fixed; |
| left:0px; |
| top:0px; |
| width:100px; |
| height:100px; |
| -ms-touch-action:none"> |
| multitouch |
| </div> |
| </body> |
| </html> |