| /* function for finding the absolute bounds of a node (both inline and block) */ |
| function findAbsoluteBounds(node) |
| { |
| var bounds = node.getBoundingClientRect(); |
| return { |
| left: bounds.left, |
| top: bounds.top, |
| width: bounds.right - bounds.left, |
| height: bounds.bottom - bounds.top |
| }; |
| } |
| |
| function nodeToString(node) |
| { |
| if (node === undefined) |
| return 'undefined'; |
| if (node === null) |
| return 'null'; |
| if (!node.nodeName) |
| return 'not a node'; |
| if (node.nodeType == 3) |
| return "'"+node.nodeValue+"'"; |
| return node.nodeName + (node.id ? ('#' + node.id) : ''); |
| } |
| |
| function boundsToString(bounds) |
| { |
| return "("+bounds.left+","+bounds.top+")x("+bounds.width+","+bounds.height+")"; |
| } |
| |
| function pointToString(point) |
| { |
| return "("+point.x+","+point.y+")"; |
| } |
| |
| |
| function shouldBeNode(adjustedNode, targetNode) { |
| if (typeof targetNode == "string") { |
| var adjustedNodeString = nodeToString(adjustedNode); |
| if (targetNode == adjustedNodeString) { |
| testPassed("adjusted node was " + targetNode + "."); |
| } |
| else { |
| testFailed("adjusted node should be " + targetNode + ". Was " + adjustedNodeString + "."); |
| } |
| return; |
| } |
| if (targetNode == adjustedNode) { |
| testPassed("adjusted node was " + nodeToString(targetNode) + "."); |
| } |
| else { |
| testFailed("adjusted node should be " + nodeToString(targetNode) + ". Was " + nodeToString(adjustedNode) + "."); |
| } |
| } |
| |
| function shouldBeWithin(adjustedPoint, targetArea) { |
| if (adjustedPoint.x >= targetArea.left && adjustedPoint.y >= targetArea.top |
| && adjustedPoint.x <= (targetArea.left + targetArea.width) |
| && adjustedPoint.y <= (targetArea.top + targetArea.height)) { |
| testPassed("adjusted point was within " + boundsToString(targetArea)); |
| } else { |
| testFailed("adjusted node should be within " + boundsToString(targetArea) + ". Was " + pointToString(adjustedPoint)); |
| } |
| } |
| |
| function testTouchPoint(touchpoint, targetNode, allowTextNodes) |
| { |
| var adjustedNode = internals.touchNodeAdjustedToBestClickableNode(touchpoint.left, touchpoint.top, touchpoint.width, touchpoint.height); |
| if (!allowTextNodes && adjustedNode && adjustedNode.nodeType == 3) |
| adjustedNode = adjustedNode.parentNode; |
| shouldBeNode(adjustedNode, targetNode); |
| } |
| |
| function testTouchPointContextMenu(touchpoint, targetNode, allowTextNodes) |
| { |
| var adjustedNode = internals.touchNodeAdjustedToBestContextMenuNode(touchpoint.left, touchpoint.top, touchpoint.width, touchpoint.height); |
| if (!allowTextNodes && adjustedNode && adjustedNode.nodeType == 3) |
| adjustedNode = adjustedNode.parentNode; |
| shouldBeNode(adjustedNode, targetNode); |
| } |
| |
| function adjustTouchPoint(touchpoint) |
| { |
| var adjustedPoint = internals.touchPositionAdjustedToBestClickableNode(touchpoint.left, touchpoint.top, touchpoint.width, touchpoint.height); |
| return adjustedPoint; |
| } |
| |
| function adjustTouchPointContextMenu(touchpoint) |
| { |
| var adjustedPoint = internals.touchPositionAdjustedToBestContextMenuNode(touchpoint.left, touchpoint.top, touchpoint.width, touchpoint.height); |
| return adjustedPoint; |
| } |
| |
| function touchPoint(x, y, radiusX, radiusY) |
| { |
| if (!radiusY) |
| radiusY = radiusX; |
| |
| return { |
| left: x - radiusX, |
| top: y - radiusY, |
| width: radiusX * 2, |
| height: radiusY * 2, |
| get x() { return this.left + this.width/2; }, |
| get y() { return this.top + this.height/2; } |
| }; |
| } |
| |
| function offsetTouchPoint(bounds, relativePosition, touchOffset, touchRadiusX, touchRadiusY) |
| { |
| if (!touchRadiusY) |
| touchRadiusY = touchRadiusX; |
| |
| // Start with the center of the touch at the top-left of the bounds. |
| var touchpoint = touchPoint(bounds.left, bounds.top, touchRadiusX, touchRadiusY); |
| |
| // Adjust the touch point as requested. |
| switch (relativePosition) { |
| case 'center': |
| touchpoint.left += bounds.width / 2; |
| touchpoint.top += bounds.height / 2; |
| break; |
| case 'left': |
| touchpoint.left -= touchOffset; |
| touchpoint.top += bounds.height / 2; |
| break; |
| case 'right': |
| touchpoint.left += bounds.width + touchOffset; |
| touchpoint.top += bounds.height / 2; |
| break; |
| case 'top-left': |
| touchpoint.left -= touchOffset; |
| touchpoint.top -= touchOffset; |
| break; |
| case 'top-right': |
| touchpoint.left += bounds.width + touchOffset; |
| touchpoint.top -= touchOffset; |
| break; |
| case 'bottom-left': |
| touchpoint.left -= touchOffset; |
| touchpoint.top += bounds.height + touchOffset; |
| break; |
| case 'bottom-right': |
| touchpoint.left += bounds.width + touchOffset; |
| touchpoint.top += bounds.height + touchOffset; |
| break; |
| case 'top': |
| touchpoint.left += bounds.width / 2; |
| touchpoint.top -= touchOffset; |
| break; |
| case 'bottom': |
| touchpoint.left += bounds.width / 2; |
| touchpoint.top += bounds.height + touchOffset; |
| } |
| |
| return touchpoint; |
| } |