Clarify targeting of touchmove and touchend events, and add tests.
authorMatt Brubeck <mbrubeck@mozilla.com>
Wed, 27 Apr 2011 07:02:31 -0700
changeset 55 7df98116715b
parent 54 be35b766b5ef
child 56 6343517cbbee
Clarify targeting of touchmove and touchend events, and add tests.
test/touchevents/single-touch.html
touchevents.html
--- a/test/touchevents/single-touch.html	Wed Apr 27 06:20:31 2011 -0700
+++ b/test/touchevents/single-touch.html	Wed Apr 27 07:02:31 2011 -0700
@@ -8,17 +8,29 @@
     setup({explicit_done: true});
 
     function run() {
-      var target = document.getElementById("target");
+      var target0 = document.getElementById("target0");
+      var target1 = document.getElementById("target1");
 
-      var test_click = async_test("Interaction with mouse events");
       var test_touchstart = async_test("touchstart event received");
+      var test_touchmove = async_test("touchmove event received");
       var test_touchend = async_test("touchend event received");
+      var test_mousedown = async_test("Interaction with mouse events");
 
       var touchstart_received = false;
+      var touchmove_received = false;
+      var touchend_received = false;
+      var invalid_touchmove_received = false;
 
-      on_event(target, "touchstart", function onTouchStart(ev) {
+      on_event(target0, "touchstart", function onTouchStart(ev) {
+        ev.preventDefault();
+
         touchstart_received = true;
+        test_touchstart.step(function() {
+          assert_false(touchmove_received, "touchstart precedes touchmove");
+          assert_false(touchend_received, "touchstart precedes touchend");
+        });
         test_touchstart.done();
+        test_mousedown.done(); // If we got here, then the mouse event test is not needed.
 
         test(function() {
           assert_true(ev.target instanceof Element, "target must be an Element.");
@@ -75,9 +87,38 @@
 
       });
 
-      on_event(target, "touchend", function onTouchStart(ev) {
+      on_event(target0, "touchmove", function onTouchMove(ev) {
+        ev.preventDefault();
+
+        if (touchmove_received)
+          return;
+        touchmove_received = true;
+
+        test_touchmove.step(function() {
+          assert_true(touchstart_received, "touchend follows touchstart");
+          assert_false(touchend_received, "touchmove precedes touchend");
+        });
+        test_touchmove.done();
+
+        test(function() {
+          assert_equals(ev.touches.length, 1, "One touch point.");
+          assert_equals(ev.changedTouches.length, 1, "One changed touch point.");
+          assert_equals(ev.targetTouches.length, 1, "One target touch point.");
+        }, "touchmove TouchList lengths are correct.");
+      });
+
+      on_event(target1, "touchmove", function onTouchMove(ev) {
+        invalid_touchmove_received = true;
+      });
+
+      on_event(window, "touchend", function onTouchStart(ev) {
+        touchend_received = true;
+
         test_touchend.step(function() {
+          assert_equals(ev.target, target0, "touchend is dispatched to the original target");
           assert_true(touchstart_received, "touchend follows touchstart");
+          assert_true(touchmove_received, "touchend follows touchmove");
+          assert_false(invalid_touchmove_received, "touchmove dispatched to correct target");
         });
         test_touchend.done();
 
@@ -123,15 +164,15 @@
       });
 
 
-      on_event(target, "click", function onClick(ev) {
-        test_click.step(function() {
+      on_event(target0, "mousedown", function onMouseDown(ev) {
+        test_mousedown.step(function() {
           assert_true(touchstart_received,
             "The touchstart event must be dispatched before any mouse " +
             "events. (If this fails, it might mean that the user agent does " +
             "not implement W3C touch events at all.)"
           );
         });
-        test_click.done();
+        test_mousedown.done();
 
         if (!touchstart_received) {
           // Abort the tests.  If touch events are not supported, then most of
@@ -143,18 +184,28 @@
     }
   </script>
   <style>
-    #target {
+    div {
+      margin: 0em;
+      padding: 2em;
+    }
+    #target0 {
       background: yellow;
       border: 1px solid orange;
-      padding: 2em;
+    }
+    #target1 {
+      background: lightblue;
+      border: 1px solid blue;
     }
   </style>
 </head>
 <body onload="run()">
   <h1>Touch area tests</h1>
-  <p id="target">
-    Tap this element with one finger (or other pointing device).
-  </p>
+  <div id="target0">
+    Touch this box with one finger (or other pointing device)...
+  </div>
+  <div id="target1">
+    ...then drag to this box and lift your finger.
+  </div>
   <div id="log"></div>
 </body>
 </html>
--- a/touchevents.html	Wed Apr 27 06:20:31 2011 -0700
+++ b/touchevents.html	Wed Apr 27 07:02:31 2011 -0700
@@ -22,7 +22,7 @@
           // subtitle   :  "an excellent document",
 
           // if you wish the publication date to be other than today, set this
-          publishDate:  "2011-04-26",
+          publishDate:  "2011-04-27",
 
           // if the specification's copyright date is a range of years, specify
           // the start date here:
@@ -122,10 +122,6 @@
             <li>if there is at least one <a>active touch event session</a>, the value of <a>identifier</a> must be the lowest integer not currently used by any active <a>Touch</a> object in any <a>active touch event session</a></li>
           </ol>
         </dd>
-        <dt>readonly attribute EventTarget target</dt>
-        <dd>
-          the original proximal event target for this <a>touch point</a>.  The target must be an <a>Element</a>.
-        </dd>
 
         <dt>readonly attribute long screenX</dt>
         <dd>
@@ -286,6 +282,8 @@
         <h3 id="event-touchstart">The <dfn class="event">touchstart</dfn> event</h3>
         <p>A user agent must dispatch this event type to indicate when the user
         places a <a>touch point</a> on the touch surface.</p>
+
+        <p>The target of this event must be an <a>Element</a>.</p>
       </section>
 
       <section>
@@ -295,6 +293,11 @@
         cases where the touch point physically leaves the touch surface, such
         as being dragged off of the screen.</p>
 
+        <p>The <a>target</a> of this event must be the same <a>Element</a> that
+        received the <a>touchstart</a> event when this <a>touch point</a> was
+        placed on the surface, even if the <a>touch point</a> has since moved
+        outside the interactive area of the <a>target</a> element.</p>
+
         <p>The <a>touch point</a> or points that were removed must be included
         in the <a>changedTouches</a> attribute of the <a>TouchEvent</a>, and
         must not be included in the <a>touches</a> and <a>targetTouches</a>
@@ -304,8 +307,12 @@
       <section>
         <h3 id="event-touchmove">The <dfn class="event">touchmove</dfn> event</h3>
         <p>A user agent must dispatch this event type to indicate when the user
-        moves a <a>touch point</a> along the touch surface, even outside the
-        interactive area of the <a>target</a> element.</p>
+        moves a <a>touch point</a> along the touch surface.
+
+        <p>The <a>target</a> of this event must be the same <a>Element</a> that
+        received the <a>touchstart</a> event when this <a>touch point</a> was
+        placed on the surface, even if the <a>touch point</a> has since moved
+        outside the interactive area of the <a>target</a> element.</p>
 
         <p>If the values of <a>radiusX</a>, <a>radiusY</a>,
         <a>rotationAngle</a>, or <a>force</a> are known, then the user agent