Pointers complete code (HTML)
This topic provides the complete code sample used in Quickstart: Pointers.
This topic contains these sections:
Download location
This sample is not available for download.
Technologies
| Programming languages | CSS, HTML, JavaScript |
|---|---|
| Programming models | Windows Runtime |
Requirements
| Minimum supported client | Windows 8 |
|---|---|
| Minimum supported server | Windows Server 2012 |
| Minimum required SDK | Microsoft Visual Studio Express 2012 for Windows 8 |
View the code ()
default.css
body {
overflow: hidden;
position: relative;
}
#grid {
display: -ms-grid;
height: 100vh; /* 100% of viewport height */
-ms-grid-columns: 4fr 1fr; /* 2 columns */
-ms-grid-rows: 1fr 320px 1fr; /* 3 rows */
/*touch-action: none;*/ /* Disable panning and zooming */
}
#targetContainer {
border:solid;
border-width:thin;
border-color: red;
-ms-grid-row: 2;
-ms-grid-column: 1;
-ms-grid-row-align: center;
-ms-grid-column-align: center;
/*touch-action: none; /* Disable panning and zooming */*/
}
#eventLog {
-ms-grid-row: 1;
-ms-grid-column: 2;
-ms-grid-row-span: 3;
padding-right: 10px;
background-color: black;
color: white;
}
.phone #target {
width: 200px;
height: 300px;
border: none;
padding: 0px;
margin: 0px;
-ms-transform-origin: 0% 0%;
/*touch-action: none; /* Disable panning and zooming */*/
}
.windows #target {
width: 400px;
height: 200px;
border: none;
padding: 0px;
margin: 0px;
-ms-transform-origin: 0% 0%;
touch-action: none; /* Disable panning and zooming */
}
default.html
Note Windows Store apps
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>PointerInput_Universal.Windows</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.2.0/js/base.js"></script> <script src="//Microsoft.WinJS.2.0/js/ui.js"></script> <!-- PointerInput_Universal.Windows references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> </head> <body class="windows"> <div id="grid"> <div id="targetContainer"> <div id="target"></div> </div> <div id="bottom"> </div> <div id="eventLog"></div> </div> </body> </html>
Note Windows Phone Store apps
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>PointerInput_Universal.WindowsPhone</title> <!-- WinJS references --> <!-- At runtime, ui-themed.css resolves to ui-themed.light.css or ui-themed.dark.css based on the user’s theme setting. This is part of the MRT resource loading functionality. --> <link href="/css/ui-themed.css" rel="stylesheet" /> <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script> <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script> <!-- PointerInput_Universal.Phone references --> <link href="/css/default.css" rel="stylesheet" /> <script src="/js/default.js"></script> </head> <body class="phone"> <div id="grid"> <div id="targetContainer"> <div id="target"></div> </div> <div id="bottom"> </div> <div id="eventLog"></div> </div> </body> </html>
default.js
(function () { "use strict"; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: This application has been newly launched. Initialize // your application here. initialize(); } else { // TODO: This application has been reactivated from suspension. // Restore application state here. } args.setPromise(WinJS.UI.processAll()); } }; app.oncheckpoint = function (args) { // TODO: This application is about to be suspended. Save any state // that needs to persist across suspensions here. You might use the // WinJS.Application.sessionState object, which is automatically // saved and restored across suspension. If you need to complete an // asynchronous operation before your application is suspended, call // args.setPromise(). }; app.start(); // For this example, we track simultaneous contacts in case the // number of contacts has reached the maximum supported by the device. // Depending on the device, additional contacts might be ignored // (PointerPressed not fired). var numActiveContacts = 0; // The input target. var target; // Target background colors corresponding to various pointer states. var pointerColor = { hover: "rgb(255, 255, 102)", down: "rgb(0, 255, 0)", up: "rgb(255, 0, 0)", cancel: "rgb(0,0,0)", out: "rgb(127,127,127)", over: "rgb(0,0,255)" }; // The event log (updated on each event). var eventLog; function initialize() { /// <summary>Set up the app.</summary> eventLog = document.getElementById("eventLog"); target = document.getElementById("target"); setTarget(); } function setTarget() { /// <summary>Set up the target and interaction event handlers.</summary> // Initial color of target. target.style.backgroundColor = pointerColor.out; // Expando dictionary property to track active contacts. // An entry is added during pointer down/hover/over events // and removed during pointer up/cancel/out/lostpointercapture events. target.pointers = []; // Declare pointer event handlers. target.addEventListener("pointerdown", onPointerDown, true); target.addEventListener("pointerover", onPointerOver, true); target.addEventListener("pointerup", onPointerUp, true); target.addEventListener("pointerout", onPointerOut, true); target.addEventListener("pointercancel", onPointerCancel, true); target.addEventListener("lostpointercapture", onLostPointerCapture, true); target.addEventListener("pointermove", onPointerMove, true); target.addEventListener("wheel", onMouseWheel, false); } // Handles pointers that are in contact and moved within the boundary of the target. // See the pointermove event for handling the hover state of a pointer that is not in contact // but is within the boundary of the target (typically a pen/stylus device). function onPointerOver(e) { /// <summary> /// Occurs when a pointer is detected within the hit test boundaries /// of an element. /// Also occurs prior to a pointerdown event for devices that do not /// support hover. /// This event type is similar to pointerenter, but bubbles. /// See the pointermove event for handling the hover state of a pointer /// that is not in contact but is within the boundary of the target /// (typically a pen/stylus device). /// </summary> /// <param name="e" type="Event">The event argument.</param> // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; // Update event details and target UI. eventLog.innerText += "\nOver: " + e.pointerId; if (target.pointers.length === 0) { // Change background color of target when pointer contact detected. if (e.getCurrentPoint(e.currentTarget).isInContact) { // Pointer down occured outside target. target.style.backgroundColor = pointerColor.down; } else { // Pointer down occured inside target. target.style.backgroundColor = pointerColor.over; } } // Check if pointer already exists. for (var i in target.pointers) { if (target.pointers[i].id = e.pointerId) { return; } } // Push new pointer Id onto expando target pointers array. target.pointers.push({ id: e.pointerId, type: e.pointerType }); // Ensure that the element continues to receive PointerEvents // even if the contact moves off the element. // Capturing the current pointer can improve usability by reducing // the touch precision required when interacting with an element. // Note: Only the assigned pointer is affected. target.setPointerCapture(e.pointerId); // Display pointer details. createInfoPop(e); } function onPointerDown(e) { /// <summary> /// Occurs for mouse when at least one mouse button is pressed or /// for touch and pen when there is physical contact with the digitizer. /// For input devices that do not support hover, the pointerover event is /// fired immediately before the pointerdown event. /// Here, we filter pointer input based on the first pointer type detected. /// </summary> /// <param name="e" type="Event">The event argument.</param> // pointerdown and pointerup events do not always occur in pairs. // Listen for and handle any event that might conclude a pointer down action // (such as pointerup, pointerout, pointercancel, and lostpointercapture). // // For this example, we track the number of contacts in case the // number of contacts has reached the maximum supported by the device. // Depending on the device, additional contacts might be ignored // (PointerPressed not fired). // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; // Check if the number of supported contacts is exceeded. var touchCapabilities = new Windows.Devices.Input.TouchCapabilities(); if ((touchCapabilities.touchPresent != 0) & (numActiveContacts > touchCapabilities.contacts)) { return; } // Update event details and target UI. eventLog.innerText += "\nDown: " + e.pointerId; target.style.backgroundColor = pointerColor.down; // Check if pointer already exists (if hover/over occurred prior to down). for (var i in target.pointers) { if (target.pointers[i].id = e.pointerId) { return; } } // Push new pointer Id onto expando target pointers array. target.pointers.push({ id: e.pointerId, type: e.pointerType }); // Ensure that the element continues to receive PointerEvents // even if the contact moves off the element. // Capturing the current pointer can improve usability by reducing // the touch precision required when interacting with an element. // Note: Only the assigned pointer is affected. target.setPointerCapture(e.pointerId); // Display pointer details. createInfoPop(e); } function onPointerUp(e) { /// <summary> /// Occurs for mouse at transition from at least one button pressed /// to no buttons pressed. /// Occurs for touch and pen when contact is removed from the digitizer. /// For input devices that do not support hover, the pointerout event /// is fired immediately after the pointerup event. /// </summary> /// <param name="e" type="Event">The event argument.</param> // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; // Update event details. eventLog.innerText += "\nUp: " + e.pointerId; // If event source is mouse pointer and the pointer is still // over the target, retain pointer and pointer details. // Return without removing pointer from pointers dictionary. // For this example, we assume a maximum of one mouse pointer. if ((e.pointerType === "mouse") & (document.elementFromPoint(e.x, e.y) === target)) { target.style.backgroundColor = pointerColor.up; return; } // Ensure capture is released on a pointer up event. target.releasePointerCapture(e.pointerId); // Remove pointer from pointers dictionary. var targetPointers = target.pointers; for (var i in targetPointers) { if (target.pointers[i].id === e.pointerId) { target.pointers.splice(i, 1); var pointerInfoPop = document.getElementById("infoPop" + e.pointerId); if (pointerInfoPop === null) return; pointerInfoPop.removeNode(true); } } // Update target UI. if (target.pointers.length === 0) { target.style.backgroundColor = pointerColor.up; } } function onPointerMove(e) { /// <summary> /// Occurs when a pointer moves within the hit test boundaries /// of an element. /// </summary> /// <param name="e" type="Event">The event argument.</param> // NOTE: Multiple, simultaneous mouse button inputs are processed here. // Mouse input is associated with a single pointer assigned when // mouse input is first detected. // Clicking additional mouse buttons (left, wheel, or right) during // the interaction creates secondary associations between those buttons // and the pointer through the pointer pressed event. // The pointer released event is fired only when the last mouse button // associated with the interaction (not necessarily the initial button) // is released. // Because of this exclusive association, other mouse button clicks are // routed through the pointer move event. // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; if (e.pointerType == "mouse") { // Mouse button states are extended PointerPoint properties. var pt = e.getCurrentPoint(e.currentTarget); var ptProperties = pt.properties; if (ptProperties.isLeftButtonPressed) { eventLog.innerText += "\nLeft button: " + e.pointerId; } if (ptProperties.isMiddleButtonPressed) { eventLog.innerText += "\nWheel button: " + e.pointerId; } if (ptProperties.isRightButtonPressed) { eventLog.innerText += "\nRight button: " + e.pointerId; } } // Handle hover state of a pointer that is not in contact but is within // the boundary of the target (typically a pen/stylus device). if (e.pointerType == "pen") { var pt = e.getCurrentPoint(e.currentTarget); if (pt.isInContact == false) { // Update event details and target UI. target.style.backgroundColor = pointerColor.hover; eventLog.innerText = "\nHover: " + e.pointerId; // Check if pointer already exists. for (var i in target.pointers) { if (target.pointers[i].id = e.pointerId) { updateInfoPop(e); return; } } target.pointers.push({ id: e.pointerId, type: e.pointerType }); // Ensure that the element continues to receive PointerEvents // even if the contact moves off the element. // Capturing the current pointer can improve usability by reducing // the touch precision required when interacting with an element. // Note: Only the assigned pointer is affected. target.setPointerCapture(e.pointerId); } } // Display pointer details. updateInfoPop(e); } function onPointerOut(e) { /// <summary> /// Occurs when a pointer (in contact or not) moves out of the /// target hit test boundary, after a pointerup event for a device /// that does not support hover, and after a pointercancel event. /// This event type is similar to pointerleave, but bubbles. /// Note: Pointer capture is maintained until pointer up event. /// </summary> /// <param name="e" type="Event">The event argument.</param> // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; // Update event details. eventLog.innerText += "\nPointer out: " + e.pointerId; // Remove pointer from pointers dictionary. var targetPointers = target.pointers; for (var i in targetPointers) { if (target.pointers[i].id === e.pointerId) { target.pointers.splice(i, 1); var pointerInfoPop = document.getElementById("infoPop" + e.pointerId); if (pointerInfoPop === null) return; pointerInfoPop.removeNode(true); // Update target UI. if (target.pointers.length === 0) { target.style.backgroundColor = pointerColor.out; } } } } function onMouseWheel(e) { /// <summary> /// Occurs when the mouse wheel is rotated. /// </summary> /// <param name="e" type="Event">The event argument.</param> // Check if a mouse pointer already exists. for (var i in target.pointers) { // Ensure existing pointer type registered with pointerover is mouse. if (target.pointers[i].type === "mouse") { e.pointerId = target.pointers[i].id; break; } } eventLog.innerText += "\nMouse wheel: " + e.pointerId; // For this example, we fire a corresponding pointer down event. onPointerDown(e); } function onPointerCancel(e) { /// <summary> /// Occurs when a pointer is removed. /// The app will not receive subsequent events for that pointer, including pointerup. /// </summary> /// <param name="e" type="Event">The event argument.</param> // A pointer can be canceled as a result of one of the following: // - A touch contact is canceled when a pen is detected. // - More than 100ms has passed since the device reported // an active contact. // - The desktop is locked or the user logged off. // - The number of simultaneous contacts exceeds the number // supported by the device. // - The system has determined that a pointer is unlikely to // continue to produce events (for example, due to a hardware event). // - After a pointerdown event, the pointer is subsequently used to // manipulate the page viewport (for example, panning or zooming). // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; // Update event details. eventLog.innerText += "\nPointer canceled: " + e.pointerId; // Ensure capture is released on a pointer cancel event. target.releasePointerCapture(e.pointerId); // Update target UI. if (target.pointers.length === 0) { target.style.backgroundColor = pointerColor.cancel; } // Remove pointer from pointers dictionary. var targetPointers = target.pointers; for (var i in targetPointers) { if (target.pointers[i].id === e.pointerId) { target.pointers.splice(i, 1); var pointerInfoPop = document.getElementById("infoPop" + e.pointerId); if (pointerInfoPop === null) return; pointerInfoPop.removeNode(true); // Update target UI. if (target.pointers.length === 0) { target.style.backgroundColor = pointerColor.out; } } } } function onLostPointerCapture(e) { /// <summary> /// Occurs after pointer capture is released for the pointer. /// </summary> /// <param name="e" type="Event">The event argument.</param> // lostpointercapture can fire instead of pointerup. // Pointer capture can be lost as a result of one of the following: // - User interactions // - Programmatic caputre of another pointer // - Captured pointer was deliberately released // Prevent the next handler in the hierarchy from receiving the event. e.cancelBubble = true; // Update event details. eventLog.innerText += "\nLost pointer capture: " + e.pointerId; // We need the device type to handle lost pointer capture from mouse input. // Use the getCurrentPoint method over currentPoint property to ensure // the coordinate space is in relation to the target element. // Note: getCurrentPoint and currentPoint are only available in the // local compartment, they are not available in the web compartment. var ptTarget = e.getCurrentPoint(e.currentTarget); var ptContainer = e.getCurrentPoint(document.getElementsByTagName("body")[0]); // If event source is mouse pointer and the pointer is still over // the target, retain pointer and pointer details. // For this example, we assume only one mouse pointer. if ((ptTarget.pointerDevice.pointerDeviceType === Windows.Devices.Input.PointerDeviceType.mouse) & (document.elementFromPoint(ptContainer.position.x, ptContainer.position.y) === target)) { target.setPointerCapture(e.pointerId); return; } // Remove pointer from pointers dictionary. var targetPointers = target.pointers; for (var i in targetPointers) { if (target.pointers[i].id === e.pointerId) { target.pointers.splice(i, 1); var pointerInfoPop = document.getElementById("infoPop" + e.pointerId); if (pointerInfoPop === null) return; pointerInfoPop.removeNode(true); } } // Update target UI. if (target.pointers.length === 0) { target.style.backgroundColor = pointerColor.cancel; } } function createInfoPop(e) { /// <summary> /// Create and insert DIV into the DOM for displaying pointer details. /// </summary> /// <param name="e" type="Event">The event argument.</param> var infoPop = document.createElement("div"); infoPop.setAttribute("id", "infoPop" + e.pointerId); // Set screen position of DIV. var transform = (new MSCSSMatrix()).translate(e.offsetX + 20, e.offsetY + 20); infoPop.style.msTransform = transform; target.appendChild(infoPop); infoPop.innerText = queryPointer(e); } function updateInfoPop(e) { /// <summary> /// Update pointer details in UI. /// </summary> /// <param name="e" type="Event">The event argument.</param> var infoPop = document.getElementById("infoPop" + e.pointerId); if (infoPop === null) return; // Set screen position of DIV. var transform = (new MSCSSMatrix()).translate(e.offsetX + 20, e.offsetY + 20); infoPop.style.msTransform = transform; infoPop.innerText = queryPointer(e); } function queryPointer(e) { /// <summary> /// Get extended pointer data. /// </summary> /// <param name="e" type="Event">The event argument.</param> // We get the extended pointer info through the getCurrentPoint method // of the event argument. (We recommend using getCurrentPoint // to ensure the coordinate space is in relation to the target.) // Note: getCurrentPoint and currentPoint are only available in the // local compartment, they are not available in the web compartment. var pt = e.getCurrentPoint(e.currentTarget); var ptTargetProperties = pt.properties; var details = "Pointer Id: " + e.pointerId; switch (e.pointerType) { case "mouse": details += "\nPointer type: mouse"; details += "\nLeft button: " + ptTargetProperties.isLeftButtonPressed; details += "\nRight button: " + ptTargetProperties.isRightButtonPressed; details += "\nWheel button: " + ptTargetProperties.isMiddleButtonPressed; details += "\nX1 button: " + ptTargetProperties.isXButton1Pressed; details += "\nX2 button: " + ptTargetProperties.isXButton2Pressed; break; case "pen": details += "\nPointer type: pen"; if (pt.isInContact) { details += "\nPressure: " + ptTargetProperties.pressure; details += "\nrotation: " + ptTargetProperties.rotation; details += "\nTilt X: " + ptTargetProperties.xtilt; details += "\nTilt Y: " + ptTargetProperties.ytilt; details += "\nBarrel button pressed: " + ptTargetProperties.isBarrelButtonPressed; } break; case "touch": details += "\nPointer type: touch"; details += "\nPressure: " + ptTargetProperties.pressure; details += "\nrotation: " + ptTargetProperties.rotation; details += "\nTilt X: " + ptTargetProperties.xtilt; details += "\nTilt Y: " + ptTargetProperties.ytilt; break; default: details += "\nPointer type: " + "n/a"; break; } details += "\nPointer location (target): " + e.offsetX + ", " + e.offsetY; details += "\nPointer location (screen): " + e.screenX + ", " + e.screenY; return details; } })();
Show: