Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Docs on releasing, alter capturing, etc. etc.

  • Loading branch information...
commit ef3927e9ac5f1b297d82de1c1357eabf3bbf002e 1 parent 2ad4481
@ialexi authored
View
2  apps/hedwig/resources/guide/touch.json
1 addition, 1 deletion not shown
View
1  apps/hedwig/views/article_view.js
@@ -50,6 +50,7 @@ Hedwig.ArticleView = SC.View.extend(Hedwig.TouchHelper, {
contentView: SC.ScrollView.design({
borderStyle: SC.BORDER_NONE,
+
contentView: SC.StaticContentView.design({
contentBinding: "Hedwig.articleController.html",
didUpdateLayer: function() {
View
9 docs/build/articles/touch/capturing.html
@@ -104,7 +104,7 @@
<h2>Touch Responder Stack</h2>
<p>Very briefly mentioned in the "Touch Events" article, the <em>touch responder</em> is the view which
-"owns" a touchthe view which gets all touchesDragged events and the touchEnd for that touch.</p>
+"owns" a touch&emdash;the view which gets all touchesDragged events and the touchEnd for that touch.</p>
<p>However, in our scroll view case, we want to pass control to the target view, but allow it
to <em>transfer control back</em> (a process covered in "Releasing"). That means it needs to know
@@ -134,7 +134,7 @@
<p>You could then use invokeLater to wait that split-second. But then what? You don't actually
know what the target view should be. What you need is to start at the original target, and
do the whole working up to it calling captureTouch and work down from it calling touchStart
-thingbut this time, starting from your own view, rather than the root. </p>
+thing&emdash;but this time, starting from your own view, rather than the root. </p>
<p>Thankfully, you can do this in one line of code:</p>
@@ -155,5 +155,10 @@
<h2>What Does It Look Like?</h2>
+<p>In this example, we have two boxes, each containing an inner box. The outer boxes
+capture touches, and only pass them to the inner box after a delay. The top box stacks,
+the other one does not; this causes, as described above, a difference in when touchEnd/Cancelled
+is called on the outer boxes.</p>
+
<p><a href='capturing.js' class='demo'>capturing.js</a></p>
</div><div class="footer"></div></body></html>
View
2  docs/build/articles/touch/capturing.js
@@ -19,6 +19,7 @@ var Tester = SC.View.extend({
// in one second, we'll pass the touch along.
this.invokeLater("beginContentTouches", 1000, touch);
+ return YES;
},
beginContentTouches: function(touch) {
@@ -45,6 +46,7 @@ var Tester = SC.View.extend({
backgroundColor: "gray",
touchStart: function() {
this.get("layer").style.backgroundColor = "blue";
+ return YES;
},
touchEnd: function() {
View
2  docs/build/articles/touch/capturing.json
@@ -1 +1 @@
-{"content":"<h1>Capturing</h1>\n\n<p>There are many instances where you may have to capture touches. We'll consider scroll views,\nhowever, because it is very easy to explain <em>why</em> they need to be able to.</p>\n\n<p>If you are implementing a scroll view, you'll need to capture the touch before the target view gets it.</p>\n\n<p>This is because scroll views have some subtle quirks. For instance, a touch should not pass\nthrough to the actual target until a split-second has passed&emdash;this is to prevent flicker should\nthe user decide to scroll rather than touch the target. Also, it needs to add itself to what is\ncalled the \"touch responder stack\" <em>before</em> the target view, so that the target view can hand control back\nsimply as discussed above.</p>\n\n<h2>Touch Responder Stack</h2>\n\n<p>Very briefly mentioned in the \"Touch Events\" article, the <em>touch responder</em> is the view which\n\"owns\" a touch\u2014the view which gets all touchesDragged events and the touchEnd for that touch.</p>\n\n<p>However, in our scroll view case, we want to pass control to the target view, but allow it\nto <em>transfer control back</em> (a process covered in \"Releasing\"). That means it needs to know\nwhat view to hand it back to. Also, what if you had a scroll view <em>within</em> a scroll view?</p>\n\n<p>To solve these issues, there is a \"stack\" of those views to which control can be passed back to.</p>\n\n<p>You generally work with it by either:</p>\n\n<ul>\n<li>Specifically telling it to \"stack\" your view when capturing a touch.</li>\n<li>Telling it to change touch responder to a touch responder in the stack (see Releasing)</li>\n</ul>\n\n<h2>Capturing</h2>\n\n<p>Capturing the touch is simple. Before starting at the target view and working its\nway up to the root calling touchStart (the same way all SproutCore events work), \nSproutCore's touch events go the opposite direction, starting at the root and working their way down\nto the target, calling a method named captureTouch:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n</code></pre>\n\n<p>If the view returns YES, the touchStart event will be sent directly to it.</p>\n\n<p>You could then use invokeLater to wait that split-second. But then what? You don't actually\nknow what the target view should be. What you need is to start at the original target, and\ndo the whole working up to it calling captureTouch and work down from it calling touchStart\nthing\u2014but this time, starting from your own view, rather than the root. </p>\n\n<p>Thankfully, you can do this in one line of code:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"class\">YES</span>); <span class=\"comment\">// the YES means stack, which I'm guessing you'd want to do</span>\n<span class=\"comment\">// so that the new view can easily pass control back to this...</span>\n<span class=\"comment\">// ... but you may know better than me.</span>\n</code></pre>\n\n<p>What happens next depends on whether or not you told it to stack your view:</p>\n\n<ul>\n<li>If stacked, you will receive a touchCancelled when the touch actually ends, unless the\nview which captures the touch hands control back to your view. If it does, you will <em>not</em>\nreceive another <code class='syntax js'><span class=\"variable\">touchStart</span></code>, but you <em>will</em> start receiving <code class='syntax js'><span class=\"variable\">touchesDragged</span></code> and \nwill receive a <code class='syntax js'><span class=\"variable\">touchEnd</span></code> when the touch ends.</li>\n<li>If not stacked, your view will receive <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>.</li>\n</ul>\n\n<h2>What Does It Look Like?</h2>\n\n<p><a href='capturing.js' class='demo'>capturing.js</a></p>","errors":[],"demos":{"capturing.js":{"ex":"/**\n This is our test view. It will capture a touch, and, after one second,\n pass it through to the child view. Depending on the shouldStack property,\n it will stack while passing.\n \n In this example, the top view stacks, the bottom one does not.\n*/\nvar Tester = SC.View.extend({\n backgroundColor: \"white\",\n \n shouldStack: NO,\n captureTouch: function() {\n return YES;\n },\n \n touchStart: function(touch) {\n this._hasTouch = touch;\n this.get(\"layer\").style.backgroundColor = \"red\";\n \n // in one second, we'll pass the touch along.\n this.invokeLater(\"beginContentTouches\", 1000, touch);\n },\n \n beginContentTouches: function(touch) {\n // if our touch hasn't changed in the meantime\n if (touch === this._hasTouch) {\n // we'll pass the touch along.\n touch.captureTouch(this, this.get(\"shouldStack\"));\n }\n },\n \n touchEnd: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n touchCancelled: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n childViews: \"inner\".w(),\n inner: SC.View.design({\n layout: { left: 50, top: 50, right: 50, bottom: 50 },\n backgroundColor: \"gray\",\n touchStart: function() {\n this.get(\"layer\").style.backgroundColor = \"blue\";\n },\n \n touchEnd: function() {\n this.get(\"layer\").style.backgroundColor = \"gray\";\n }\n \n })\n \n});\n\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"#aaa\",\n childViews: \"stacks doesNot\".w(),\n stacks: Tester.extend({\n layout: { top: 10, left: 10, width: 200, height: 200 },\n shouldStack: YES\n }),\n \n doesNot: Tester.extend({\n layout: { top: 230, left: 10, width: 200, height: 200 },\n shouldStack: NO \n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n","highlighted":"<span class=\"multiline comment\">/**\n This is our test view. It will capture a touch, and, after one second,\n pass it through to the child view. Depending on the shouldStack property,\n it will stack while passing.\n \n In this example, the top view stacks, the bottom one does not.\n*/</span>\n<span class=\"keyword\">var</span> <span class=\"class\">Tester</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;white&quot;</span>,\n \n <span class=\"variable\">shouldStack</span>: <span class=\"class\">NO</span>,\n <span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"variable\">touch</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;red&quot;</span>;\n \n <span class=\"comment\">// in one second, we'll pass the touch along.</span>\n <span class=\"this\">this</span>.<span class=\"variable\">invokeLater</span>(<span class=\"string\">&quot;beginContentTouches&quot;</span>, <span class=\"number integer\">1000</span>, <span class=\"variable\">touch</span>);\n },\n \n <span class=\"variable\">beginContentTouches</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"comment\">// if our touch hasn't changed in the meantime</span>\n <span class=\"keyword\">if</span> (<span class=\"variable\">touch</span> === <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span>) {\n <span class=\"comment\">// we'll pass the touch along.</span>\n <span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;shouldStack&quot;</span>));\n }\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;white&quot;</span>;\n },\n \n <span class=\"variable\">touchCancelled</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;white&quot;</span>;\n },\n \n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;inner&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">inner</span>: <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">left</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">top</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">right</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">bottom</span>: <span class=\"number integer\">50</span> },\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;gray&quot;</span>,\n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>() {\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;blue&quot;</span>;\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>() {\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;gray&quot;</span>;\n }\n \n })\n \n});\n\n<span class=\"keyword\">var</span> <span class=\"class\">MyExampleView</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;#aaa&quot;</span>,\n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;stacks doesNot&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">stacks</span>: <span class=\"class\">Tester</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">top</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">200</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">200</span> },\n <span class=\"variable\">shouldStack</span>: <span class=\"class\">YES</span>\n }),\n \n <span class=\"variable\">doesNot</span>: <span class=\"class\">Tester</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">top</span>: <span class=\"number integer\">230</span>, <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">200</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">200</span> },\n <span class=\"variable\">shouldStack</span>: <span class=\"class\">NO</span> \n })\n});\n\n<span class=\"comment\">// bootstrap code :)</span>\n<span class=\"variable\">exports</span>.<span class=\"variable\">getDemoView</span> = <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">MyExampleView</span>;\n};\n","original":"/**\n This is our test view. It will capture a touch, and, after one second,\n pass it through to the child view. Depending on the shouldStack property,\n it will stack while passing.\n \n In this example, the top view stacks, the bottom one does not.\n*/\nvar Tester = SC.View.extend({\n backgroundColor: \"white\",\n \n shouldStack: NO,\n captureTouch: function() {\n return YES;\n },\n \n touchStart: function(touch) {\n this._hasTouch = touch;\n this.get(\"layer\").style.backgroundColor = \"red\";\n \n // in one second, we'll pass the touch along.\n this.invokeLater(\"beginContentTouches\", 1000, touch);\n },\n \n beginContentTouches: function(touch) {\n // if our touch hasn't changed in the meantime\n if (touch === this._hasTouch) {\n // we'll pass the touch along.\n touch.captureTouch(this, this.get(\"shouldStack\"));\n }\n },\n \n touchEnd: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n touchCancelled: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n childViews: \"inner\".w(),\n inner: SC.View.design({\n layout: { left: 50, top: 50, right: 50, bottom: 50 },\n backgroundColor: \"gray\",\n touchStart: function() {\n this.get(\"layer\").style.backgroundColor = \"blue\";\n },\n \n touchEnd: function() {\n this.get(\"layer\").style.backgroundColor = \"gray\";\n }\n \n })\n \n});\n\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"#aaa\",\n childViews: \"stacks doesNot\".w(),\n stacks: Tester.extend({\n layout: { top: 10, left: 10, width: 200, height: 200 },\n shouldStack: YES\n }),\n \n doesNot: Tester.extend({\n layout: { top: 230, left: 10, width: 200, height: 200 },\n shouldStack: NO \n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n"}},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Capturing"}
+{"content":"<h1>Capturing</h1>\n\n<p>There are many instances where you may have to capture touches. We'll consider scroll views,\nhowever, because it is very easy to explain <em>why</em> they need to be able to.</p>\n\n<p>If you are implementing a scroll view, you'll need to capture the touch before the target view gets it.</p>\n\n<p>This is because scroll views have some subtle quirks. For instance, a touch should not pass\nthrough to the actual target until a split-second has passed&emdash;this is to prevent flicker should\nthe user decide to scroll rather than touch the target. Also, it needs to add itself to what is\ncalled the \"touch responder stack\" <em>before</em> the target view, so that the target view can hand control back\nsimply as discussed above.</p>\n\n<h2>Touch Responder Stack</h2>\n\n<p>Very briefly mentioned in the \"Touch Events\" article, the <em>touch responder</em> is the view which\n\"owns\" a touch&emdash;the view which gets all touchesDragged events and the touchEnd for that touch.</p>\n\n<p>However, in our scroll view case, we want to pass control to the target view, but allow it\nto <em>transfer control back</em> (a process covered in \"Releasing\"). That means it needs to know\nwhat view to hand it back to. Also, what if you had a scroll view <em>within</em> a scroll view?</p>\n\n<p>To solve these issues, there is a \"stack\" of those views to which control can be passed back to.</p>\n\n<p>You generally work with it by either:</p>\n\n<ul>\n<li>Specifically telling it to \"stack\" your view when capturing a touch.</li>\n<li>Telling it to change touch responder to a touch responder in the stack (see Releasing)</li>\n</ul>\n\n<h2>Capturing</h2>\n\n<p>Capturing the touch is simple. Before starting at the target view and working its\nway up to the root calling touchStart (the same way all SproutCore events work), \nSproutCore's touch events go the opposite direction, starting at the root and working their way down\nto the target, calling a method named captureTouch:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n</code></pre>\n\n<p>If the view returns YES, the touchStart event will be sent directly to it.</p>\n\n<p>You could then use invokeLater to wait that split-second. But then what? You don't actually\nknow what the target view should be. What you need is to start at the original target, and\ndo the whole working up to it calling captureTouch and work down from it calling touchStart\nthing&emdash;but this time, starting from your own view, rather than the root. </p>\n\n<p>Thankfully, you can do this in one line of code:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"class\">YES</span>); <span class=\"comment\">// the YES means stack, which I'm guessing you'd want to do</span>\n<span class=\"comment\">// so that the new view can easily pass control back to this...</span>\n<span class=\"comment\">// ... but you may know better than me.</span>\n</code></pre>\n\n<p>What happens next depends on whether or not you told it to stack your view:</p>\n\n<ul>\n<li>If stacked, you will receive a touchCancelled when the touch actually ends, unless the\nview which captures the touch hands control back to your view. If it does, you will <em>not</em>\nreceive another <code class='syntax js'><span class=\"variable\">touchStart</span></code>, but you <em>will</em> start receiving <code class='syntax js'><span class=\"variable\">touchesDragged</span></code> and \nwill receive a <code class='syntax js'><span class=\"variable\">touchEnd</span></code> when the touch ends.</li>\n<li>If not stacked, your view will receive <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>.</li>\n</ul>\n\n<h2>What Does It Look Like?</h2>\n\n<p>In this example, we have two boxes, each containing an inner box. The outer boxes\ncapture touches, and only pass them to the inner box after a delay. The top box stacks,\nthe other one does not; this causes, as described above, a difference in when touchEnd/Cancelled\nis called on the outer boxes.</p>\n\n<p><a href='capturing.js' class='demo'>capturing.js</a></p>","errors":[],"demos":{"capturing.js":{"ex":"/**\n This is our test view. It will capture a touch, and, after one second,\n pass it through to the child view. Depending on the shouldStack property,\n it will stack while passing.\n \n In this example, the top view stacks, the bottom one does not.\n*/\nvar Tester = SC.View.extend({\n backgroundColor: \"white\",\n \n shouldStack: NO,\n captureTouch: function() {\n return YES;\n },\n \n touchStart: function(touch) {\n this._hasTouch = touch;\n this.get(\"layer\").style.backgroundColor = \"red\";\n \n // in one second, we'll pass the touch along.\n this.invokeLater(\"beginContentTouches\", 1000, touch);\n return YES;\n },\n \n beginContentTouches: function(touch) {\n // if our touch hasn't changed in the meantime\n if (touch === this._hasTouch) {\n // we'll pass the touch along.\n touch.captureTouch(this, this.get(\"shouldStack\"));\n }\n },\n \n touchEnd: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n touchCancelled: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n childViews: \"inner\".w(),\n inner: SC.View.design({\n layout: { left: 50, top: 50, right: 50, bottom: 50 },\n backgroundColor: \"gray\",\n touchStart: function() {\n this.get(\"layer\").style.backgroundColor = \"blue\";\n return YES;\n },\n \n touchEnd: function() {\n this.get(\"layer\").style.backgroundColor = \"gray\";\n }\n \n })\n \n});\n\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"#aaa\",\n childViews: \"stacks doesNot\".w(),\n stacks: Tester.extend({\n layout: { top: 10, left: 10, width: 200, height: 200 },\n shouldStack: YES\n }),\n \n doesNot: Tester.extend({\n layout: { top: 230, left: 10, width: 200, height: 200 },\n shouldStack: NO \n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n","highlighted":"<span class=\"multiline comment\">/**\n This is our test view. It will capture a touch, and, after one second,\n pass it through to the child view. Depending on the shouldStack property,\n it will stack while passing.\n \n In this example, the top view stacks, the bottom one does not.\n*/</span>\n<span class=\"keyword\">var</span> <span class=\"class\">Tester</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;white&quot;</span>,\n \n <span class=\"variable\">shouldStack</span>: <span class=\"class\">NO</span>,\n <span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"variable\">touch</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;red&quot;</span>;\n \n <span class=\"comment\">// in one second, we'll pass the touch along.</span>\n <span class=\"this\">this</span>.<span class=\"variable\">invokeLater</span>(<span class=\"string\">&quot;beginContentTouches&quot;</span>, <span class=\"number integer\">1000</span>, <span class=\"variable\">touch</span>);\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">beginContentTouches</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"comment\">// if our touch hasn't changed in the meantime</span>\n <span class=\"keyword\">if</span> (<span class=\"variable\">touch</span> === <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span>) {\n <span class=\"comment\">// we'll pass the touch along.</span>\n <span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;shouldStack&quot;</span>));\n }\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;white&quot;</span>;\n },\n \n <span class=\"variable\">touchCancelled</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;white&quot;</span>;\n },\n \n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;inner&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">inner</span>: <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">left</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">top</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">right</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">bottom</span>: <span class=\"number integer\">50</span> },\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;gray&quot;</span>,\n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>() {\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;blue&quot;</span>;\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>() {\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;gray&quot;</span>;\n }\n \n })\n \n});\n\n<span class=\"keyword\">var</span> <span class=\"class\">MyExampleView</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;#aaa&quot;</span>,\n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;stacks doesNot&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">stacks</span>: <span class=\"class\">Tester</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">top</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">200</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">200</span> },\n <span class=\"variable\">shouldStack</span>: <span class=\"class\">YES</span>\n }),\n \n <span class=\"variable\">doesNot</span>: <span class=\"class\">Tester</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">top</span>: <span class=\"number integer\">230</span>, <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">200</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">200</span> },\n <span class=\"variable\">shouldStack</span>: <span class=\"class\">NO</span> \n })\n});\n\n<span class=\"comment\">// bootstrap code :)</span>\n<span class=\"variable\">exports</span>.<span class=\"variable\">getDemoView</span> = <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">MyExampleView</span>;\n};\n","original":"/**\n This is our test view. It will capture a touch, and, after one second,\n pass it through to the child view. Depending on the shouldStack property,\n it will stack while passing.\n \n In this example, the top view stacks, the bottom one does not.\n*/\nvar Tester = SC.View.extend({\n backgroundColor: \"white\",\n \n shouldStack: NO,\n captureTouch: function() {\n return YES;\n },\n \n touchStart: function(touch) {\n this._hasTouch = touch;\n this.get(\"layer\").style.backgroundColor = \"red\";\n \n // in one second, we'll pass the touch along.\n this.invokeLater(\"beginContentTouches\", 1000, touch);\n return YES;\n },\n \n beginContentTouches: function(touch) {\n // if our touch hasn't changed in the meantime\n if (touch === this._hasTouch) {\n // we'll pass the touch along.\n touch.captureTouch(this, this.get(\"shouldStack\"));\n }\n },\n \n touchEnd: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n touchCancelled: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n childViews: \"inner\".w(),\n inner: SC.View.design({\n layout: { left: 50, top: 50, right: 50, bottom: 50 },\n backgroundColor: \"gray\",\n touchStart: function() {\n this.get(\"layer\").style.backgroundColor = \"blue\";\n return YES;\n },\n \n touchEnd: function() {\n this.get(\"layer\").style.backgroundColor = \"gray\";\n }\n \n })\n \n});\n\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"#aaa\",\n childViews: \"stacks doesNot\".w(),\n stacks: Tester.extend({\n layout: { top: 10, left: 10, width: 200, height: 200 },\n shouldStack: YES\n }),\n \n doesNot: Tester.extend({\n layout: { top: 230, left: 10, width: 200, height: 200 },\n shouldStack: NO \n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n"}},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Capturing"}
View
5 docs/build/articles/touch/capturing.md
@@ -61,6 +61,11 @@ What happens next depends on whether or not you told it to stack your view:
What Does It Look Like?
-----------------------
+In this example, we have two boxes, each containing an inner box. The outer boxes
+capture touches, and only pass them to the inner box after a delay. The top box stacks,
+the other one does not; this causes, as described above, a difference in when touchEnd/Cancelled
+is called on the outer boxes.
+
{{demo:sc|capturing.js}}
View
4 docs/build/articles/touch/internals.html
@@ -253,7 +253,7 @@
touch responder stack <em>before</em> the target view, so that the target view can hand control back
simply as discussed above.</p>
-<p>The first partcapturing the touchis simple. Before starting at the target view and working its
+<p>The first part&emdash;capturing the touch&emdash;is simple. Before starting at the target view and working its
way up to the root calling touchStart, SproutCore's touch events go the opposite direction, starting
at the root and working their way down to the target, calling a method named captureTouch:</p>
@@ -265,7 +265,7 @@
<p>You could then use invokeLater to wait that split-second. But then what? You don't actually
know what the target view should be. What you need is to start at the original target, and
do the whole working up to it calling captureTouch and work down from it calling touchStart
-thingbut this time, starting from your own view, rather than the root. </p>
+thing&emdash;but this time, starting from your own view, rather than the root. </p>
<p>Thankfully, you can do this in one line of code:</p>
View
2  docs/build/articles/touch/internals.json
@@ -1 +1 @@
-{"content":"<h1>Touch Events</h1>\n\n<p>SproutCore now supports multitouch.</p>\n\n<p>Views ought to implement four methods to support touch:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">touchStart</span></code></li>\n<li><code class='syntax js'><span class=\"variable\">touchEnd</span></code></li>\n<li><code class='syntax js'><span class=\"variable\">touchCancelled</span></code></li>\n<li><code class='syntax js'><span class=\"variable\">touchesDragged</span></code></li>\n</ul>\n\n<p>The methods are what they sound like. Really.</p>\n\n<p>So, understanding that, why do three start with <code class='syntax js'><span class=\"variable\">touch</span></code>-, and one starts with <code class='syntax js'><span class=\"variable\">touches</span></code>-? There is\nindeed a very logical and important reason: the ones with names starting with <code class='syntax js'><span class=\"variable\">touch</span></code> deal\nwith single touches at a time. The one starting with \"touches\" deals with potentially multiple touches.</p>\n\n<h2>Finding the Touch Responder</h2>\n\n<p>When a user first touches the screen, a touch responder for that touch is found. The touch responder\nis the view that receives all further touch events for that touch, such as touchesDragged, touchEnd,\nand touchCancelled.</p>\n\n<p>The process is simple. First, it finds out what view the touch was targeted at originally. Then it\ndoes some special stuff (which we'll discuss under 'Capturing Touch') for special views like <code>SC.ScrollView</code>s. \nFinally, it starts at the target view and works up the view tree until it finds a view that <em>accepts</em> the touch.\nThis view becomes the touch responder for the touch, and will receive further events \n(<code class='syntax js'><span class=\"variable\">touchStart</span></code>, <code class='syntax js'><span class=\"variable\">touchesDragged</span></code>, and <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>);</p>\n\n<h1>Accepting the Touch: touchStart</h1>\n\n<p>To accept a touch, a view must return <code class='syntax js'><span class=\"class\">YES</span></code> from <code class='syntax js'><span class=\"variable\">touchStart</span></code>.</p>\n\n<p>How does a view know if it wants to accept the touch? You are possibly familiar with <code class='syntax js'><span class=\"variable\">mouseDown</span></code>'s signature:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n</code></pre>\n\n<p>With <code class='syntax js'><span class=\"variable\">mouseDown</span></code>, you can decide whether or not to accept the touch based on, for instance, the <code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"class\">Y</span></code>\nof the mouse.</p>\n\n<p>touchStart's signature is slightly different:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n</code></pre>\n\n<p><code class='syntax js'><span class=\"variable\">touchStart</span></code>, instead of being passed the raw event, is passed an <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> object. </p>\n\n<h2>Tip: set acceptsMultitouch to YES to track multiple touches</h2>\n\n<p>By default, views will only receive <code class='syntax js'><span class=\"variable\">touchStart</span></code> for the <em>first</em> finger to touch them,\nand touchEnd for the <em>last</em> finger to lift from them. This is to make it simpler to\nhandle views such as buttons, which don't need to track multiple touches.</p>\n\n<p>To track multiple touches, set your view's <code class='syntax js'><span class=\"variable\">acceptsMultitouch</span></code> property to <code class='syntax js'><span class=\"class\">YES</span></code>.</p>\n\n<h2>SC.Touch</h2>\n\n<p>SC.Touch represents the touch from the time the user puts their finger on the screen until the time they lift it.</p>\n\n<p>The touch object acts like an event object in many ways. It has many other useful things, as well:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> for the touch</li>\n<li><code class='syntax js'><span class=\"variable\">event</span></code>: if in an event cycle, this contains the event. Otherwise, it is <code class='syntax js'><span class=\"variable\">undefined</span></code>.</li>\n<li><code class='syntax js'><span class=\"variable\">preventDefault</span></code>: if the touch is connected with an event, this calls <code class='syntax js'><span class=\"variable\">preventDefault</span>()</code> on the event.</li>\n<li><code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"variable\">view</span>)</code>: when supplied a view, will find all touches that the view is the\ntouch responder for. It is a CoreSet; to get an array, call <code class='syntax js'>.<span class=\"variable\">toArray</span></code> on the result.</li>\n</ul>\n\n<p>Note: If you call <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>, the touch supplied to <code class='syntax js'><span class=\"variable\">touchStart</span></code> will not be in the set,\nas the view has not accepted it yet.</p>\n\n<h1>Tracking Movement: touchesDragged</h1>\n\n<p><code class='syntax js'><span class=\"variable\">touchesDragged</span></code> will be called on a touch's touch responder every time a touch \n(or multiple touches) moves. Unlike <code class='syntax js'><span class=\"variable\">touchStart</span></code>, <code class='syntax js'><span class=\"variable\">touchEnd</span></code>, and <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>, which are\ncalled once per touch, <code class='syntax js'><span class=\"variable\">touchesDragged</span></code> is called once per event cycle, and can be called\nwith multiple touches.</p>\n\n<p><code class='syntax js'><span class=\"variable\">touchesDragged</span></code> signature is:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchesDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>, <span class=\"variable\">touches</span>) {\n</code></pre>\n\n<p><code class='syntax js'><span class=\"variable\">evt</span></code> is relatively standard, except for the following:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> are set to the <code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> of the first touch</li>\n<li>the event has a <code class='syntax js'><span class=\"variable\">touchesForView</span></code> method (though you probably won't use it\u2013see \"touches\")</li>\n</ul>\n\n<p>In addition to the event, the CoreSet of touches for the view (that is, for which the view\nis touch responder) is provided (this is why you don't have to call <code class='syntax js'><span class=\"variable\">touchesForView</span></code>).\nIt is a CoreSet of <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> objects (the same as if you called <code class='syntax js'><span class=\"variable\">touchesForView</span></code>).</p>\n\n<h1>Ending Touches: touchEnd</h1>\n\n<p>Do I really need to explain? Like <code class='syntax js'><span class=\"variable\">touchStart</span></code>, it is passed an <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> object. This touch will\nnot be in the set of touches for the view, because it has ended.</p>\n\n<h1>Cancelling Touches: touchCancelled</h1>\n\n<p>Basically, <code class='syntax js'><span class=\"variable\">touchCancelled</span></code> is like <code class='syntax js'><span class=\"variable\">touchEnd</span></code>, except it occurs when the touch was cancelled for\nsome other reason. For instance, if a button receives <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>, it should make the button\nstop being active, but should <em>not</em> trigger the button's action.</p>\n\n<h1>Giving Up Touches</h1>\n\n<p>Why would you want to give up a touch? Imagine that your control is inside a <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">ScrollView</span></code>:\nif the touch moves too much, perhaps it should be considered a scroll, rather than an\naction for your control.</p>\n\n<p>From touchesDragged, you would give up touch responder status through a line like this:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">someTouch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">someTouch</span>.<span class=\"variable\">nextTouchResponder</span>);\n</code></pre>\n\n<p>The touch's nextTouchResponder is the responder that is the <em>parent</em> touch responder; through\ndevious trickery (see <em>Capturing Touches</em>), ScrollView receives touch responder status <em>before</em>\nother views; further, it doesn't just hand touch responder status to the target view (your view)--\nit adds the responder to a stack of touch responders for the touch, so the responders can easily\nreturn to their parent responder (which is what you do with the above line of code.)</p>\n\n<p>Remember, though, that touchesDragged is called with a set of touches. It is really easy\nto change the responder for all of the touches simultaneously, should you wish to do so:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touches</span>.<span class=\"variable\">forEach</span>(<span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>){\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n});\n</code></pre>\n\n<p>Perhaps you want to pass control only if the responder is scrollable:</p>\n\n<pre><code class='syntax js'><span class=\"keyword\">if</span> (<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span> &amp;&amp; <span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>.<span class=\"variable\">isScrollable</span>) {\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n}\n</code></pre>\n\n<p>You can also stack your touch responder on so that child views may easily return control back\nto your view:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>, <span class=\"class\">YES</span>); <span class=\"comment\">// YES as shouldStack argument</span>\n</code></pre>\n\n<p><strong>If your view is no longer in the touch responder stack, touchCancelled will be called upon it.</strong>\nThis means that, if shouldStack is YES (and as such the view was not removed), no touchCancelled\nwould be called; on the other hand, if you were returning control to the original view (returning to\nthe scroll view, for example), touchCancelled will be called.</p>\n\n<p>Also note that, when touchEnd occurs, it will trigger touchEnd only for the main touchResponder; all\nother responders will get touchCancelled.</p>\n\n<h1>Advanced: Capturing Touches</h1>\n\n<p>Implementing a Scroll view? You'll need to capture the touch before the target view gets it.</p>\n\n<p>This is because Scroll views have some subtle quirks. For instance, a touch should not pass\nthrough to the actual target until a split-second has passed&emdash;this is to prevent flicker should\nthe user decide to scroll rather than touch the target. Also, it needs to add itself to the\ntouch responder stack <em>before</em> the target view, so that the target view can hand control back\nsimply as discussed above.</p>\n\n<p>The first part\u2014capturing the touch\u2014is simple. Before starting at the target view and working its\nway up to the root calling touchStart, SproutCore's touch events go the opposite direction, starting\nat the root and working their way down to the target, calling a method named captureTouch:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n</code></pre>\n\n<p>If the view returns YES, the touchStart event will be sent directly to it.</p>\n\n<p>You could then use invokeLater to wait that split-second. But then what? You don't actually\nknow what the target view should be. What you need is to start at the original target, and\ndo the whole working up to it calling captureTouch and work down from it calling touchStart\nthing\u2014but this time, starting from your own view, rather than the root. </p>\n\n<p>Thankfully, you can do this in one line of code:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"class\">YES</span>); <span class=\"comment\">// the YES means stack, which I'm guessing you'd want to do</span>\n<span class=\"comment\">// so that the new view can easily pass control back to this...</span>\n<span class=\"comment\">// ... but you may know better than me</span>\n</code></pre>\n\n<p>If the view returns the event back to you, your view will begin getting touchesDragged events and\nwill receive touchEnd when the touch ends (you will not receive another touchStart event, however). \nOtherwise, your view will receive a touchCancelled when the touch ends.</p>","errors":[],"demos":{},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Touch Events"}
+{"content":"<h1>Touch Events</h1>\n\n<p>SproutCore now supports multitouch.</p>\n\n<p>Views ought to implement four methods to support touch:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">touchStart</span></code></li>\n<li><code class='syntax js'><span class=\"variable\">touchEnd</span></code></li>\n<li><code class='syntax js'><span class=\"variable\">touchCancelled</span></code></li>\n<li><code class='syntax js'><span class=\"variable\">touchesDragged</span></code></li>\n</ul>\n\n<p>The methods are what they sound like. Really.</p>\n\n<p>So, understanding that, why do three start with <code class='syntax js'><span class=\"variable\">touch</span></code>-, and one starts with <code class='syntax js'><span class=\"variable\">touches</span></code>-? There is\nindeed a very logical and important reason: the ones with names starting with <code class='syntax js'><span class=\"variable\">touch</span></code> deal\nwith single touches at a time. The one starting with \"touches\" deals with potentially multiple touches.</p>\n\n<h2>Finding the Touch Responder</h2>\n\n<p>When a user first touches the screen, a touch responder for that touch is found. The touch responder\nis the view that receives all further touch events for that touch, such as touchesDragged, touchEnd,\nand touchCancelled.</p>\n\n<p>The process is simple. First, it finds out what view the touch was targeted at originally. Then it\ndoes some special stuff (which we'll discuss under 'Capturing Touch') for special views like <code>SC.ScrollView</code>s. \nFinally, it starts at the target view and works up the view tree until it finds a view that <em>accepts</em> the touch.\nThis view becomes the touch responder for the touch, and will receive further events \n(<code class='syntax js'><span class=\"variable\">touchStart</span></code>, <code class='syntax js'><span class=\"variable\">touchesDragged</span></code>, and <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>);</p>\n\n<h1>Accepting the Touch: touchStart</h1>\n\n<p>To accept a touch, a view must return <code class='syntax js'><span class=\"class\">YES</span></code> from <code class='syntax js'><span class=\"variable\">touchStart</span></code>.</p>\n\n<p>How does a view know if it wants to accept the touch? You are possibly familiar with <code class='syntax js'><span class=\"variable\">mouseDown</span></code>'s signature:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n</code></pre>\n\n<p>With <code class='syntax js'><span class=\"variable\">mouseDown</span></code>, you can decide whether or not to accept the touch based on, for instance, the <code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"class\">Y</span></code>\nof the mouse.</p>\n\n<p>touchStart's signature is slightly different:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n</code></pre>\n\n<p><code class='syntax js'><span class=\"variable\">touchStart</span></code>, instead of being passed the raw event, is passed an <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> object. </p>\n\n<h2>Tip: set acceptsMultitouch to YES to track multiple touches</h2>\n\n<p>By default, views will only receive <code class='syntax js'><span class=\"variable\">touchStart</span></code> for the <em>first</em> finger to touch them,\nand touchEnd for the <em>last</em> finger to lift from them. This is to make it simpler to\nhandle views such as buttons, which don't need to track multiple touches.</p>\n\n<p>To track multiple touches, set your view's <code class='syntax js'><span class=\"variable\">acceptsMultitouch</span></code> property to <code class='syntax js'><span class=\"class\">YES</span></code>.</p>\n\n<h2>SC.Touch</h2>\n\n<p>SC.Touch represents the touch from the time the user puts their finger on the screen until the time they lift it.</p>\n\n<p>The touch object acts like an event object in many ways. It has many other useful things, as well:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> for the touch</li>\n<li><code class='syntax js'><span class=\"variable\">event</span></code>: if in an event cycle, this contains the event. Otherwise, it is <code class='syntax js'><span class=\"variable\">undefined</span></code>.</li>\n<li><code class='syntax js'><span class=\"variable\">preventDefault</span></code>: if the touch is connected with an event, this calls <code class='syntax js'><span class=\"variable\">preventDefault</span>()</code> on the event.</li>\n<li><code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"variable\">view</span>)</code>: when supplied a view, will find all touches that the view is the\ntouch responder for. It is a CoreSet; to get an array, call <code class='syntax js'>.<span class=\"variable\">toArray</span></code> on the result.</li>\n</ul>\n\n<p>Note: If you call <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>, the touch supplied to <code class='syntax js'><span class=\"variable\">touchStart</span></code> will not be in the set,\nas the view has not accepted it yet.</p>\n\n<h1>Tracking Movement: touchesDragged</h1>\n\n<p><code class='syntax js'><span class=\"variable\">touchesDragged</span></code> will be called on a touch's touch responder every time a touch \n(or multiple touches) moves. Unlike <code class='syntax js'><span class=\"variable\">touchStart</span></code>, <code class='syntax js'><span class=\"variable\">touchEnd</span></code>, and <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>, which are\ncalled once per touch, <code class='syntax js'><span class=\"variable\">touchesDragged</span></code> is called once per event cycle, and can be called\nwith multiple touches.</p>\n\n<p><code class='syntax js'><span class=\"variable\">touchesDragged</span></code> signature is:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchesDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>, <span class=\"variable\">touches</span>) {\n</code></pre>\n\n<p><code class='syntax js'><span class=\"variable\">evt</span></code> is relatively standard, except for the following:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> are set to the <code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> of the first touch</li>\n<li>the event has a <code class='syntax js'><span class=\"variable\">touchesForView</span></code> method (though you probably won't use it\u2013see \"touches\")</li>\n</ul>\n\n<p>In addition to the event, the CoreSet of touches for the view (that is, for which the view\nis touch responder) is provided (this is why you don't have to call <code class='syntax js'><span class=\"variable\">touchesForView</span></code>).\nIt is a CoreSet of <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> objects (the same as if you called <code class='syntax js'><span class=\"variable\">touchesForView</span></code>).</p>\n\n<h1>Ending Touches: touchEnd</h1>\n\n<p>Do I really need to explain? Like <code class='syntax js'><span class=\"variable\">touchStart</span></code>, it is passed an <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> object. This touch will\nnot be in the set of touches for the view, because it has ended.</p>\n\n<h1>Cancelling Touches: touchCancelled</h1>\n\n<p>Basically, <code class='syntax js'><span class=\"variable\">touchCancelled</span></code> is like <code class='syntax js'><span class=\"variable\">touchEnd</span></code>, except it occurs when the touch was cancelled for\nsome other reason. For instance, if a button receives <code class='syntax js'><span class=\"variable\">touchCancelled</span></code>, it should make the button\nstop being active, but should <em>not</em> trigger the button's action.</p>\n\n<h1>Giving Up Touches</h1>\n\n<p>Why would you want to give up a touch? Imagine that your control is inside a <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">ScrollView</span></code>:\nif the touch moves too much, perhaps it should be considered a scroll, rather than an\naction for your control.</p>\n\n<p>From touchesDragged, you would give up touch responder status through a line like this:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">someTouch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">someTouch</span>.<span class=\"variable\">nextTouchResponder</span>);\n</code></pre>\n\n<p>The touch's nextTouchResponder is the responder that is the <em>parent</em> touch responder; through\ndevious trickery (see <em>Capturing Touches</em>), ScrollView receives touch responder status <em>before</em>\nother views; further, it doesn't just hand touch responder status to the target view (your view)--\nit adds the responder to a stack of touch responders for the touch, so the responders can easily\nreturn to their parent responder (which is what you do with the above line of code.)</p>\n\n<p>Remember, though, that touchesDragged is called with a set of touches. It is really easy\nto change the responder for all of the touches simultaneously, should you wish to do so:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touches</span>.<span class=\"variable\">forEach</span>(<span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>){\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n});\n</code></pre>\n\n<p>Perhaps you want to pass control only if the responder is scrollable:</p>\n\n<pre><code class='syntax js'><span class=\"keyword\">if</span> (<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span> &amp;&amp; <span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>.<span class=\"variable\">isScrollable</span>) {\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n}\n</code></pre>\n\n<p>You can also stack your touch responder on so that child views may easily return control back\nto your view:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>, <span class=\"class\">YES</span>); <span class=\"comment\">// YES as shouldStack argument</span>\n</code></pre>\n\n<p><strong>If your view is no longer in the touch responder stack, touchCancelled will be called upon it.</strong>\nThis means that, if shouldStack is YES (and as such the view was not removed), no touchCancelled\nwould be called; on the other hand, if you were returning control to the original view (returning to\nthe scroll view, for example), touchCancelled will be called.</p>\n\n<p>Also note that, when touchEnd occurs, it will trigger touchEnd only for the main touchResponder; all\nother responders will get touchCancelled.</p>\n\n<h1>Advanced: Capturing Touches</h1>\n\n<p>Implementing a Scroll view? You'll need to capture the touch before the target view gets it.</p>\n\n<p>This is because Scroll views have some subtle quirks. For instance, a touch should not pass\nthrough to the actual target until a split-second has passed&emdash;this is to prevent flicker should\nthe user decide to scroll rather than touch the target. Also, it needs to add itself to the\ntouch responder stack <em>before</em> the target view, so that the target view can hand control back\nsimply as discussed above.</p>\n\n<p>The first part&emdash;capturing the touch&emdash;is simple. Before starting at the target view and working its\nway up to the root calling touchStart, SproutCore's touch events go the opposite direction, starting\nat the root and working their way down to the target, calling a method named captureTouch:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n</code></pre>\n\n<p>If the view returns YES, the touchStart event will be sent directly to it.</p>\n\n<p>You could then use invokeLater to wait that split-second. But then what? You don't actually\nknow what the target view should be. What you need is to start at the original target, and\ndo the whole working up to it calling captureTouch and work down from it calling touchStart\nthing&emdash;but this time, starting from your own view, rather than the root. </p>\n\n<p>Thankfully, you can do this in one line of code:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"class\">YES</span>); <span class=\"comment\">// the YES means stack, which I'm guessing you'd want to do</span>\n<span class=\"comment\">// so that the new view can easily pass control back to this...</span>\n<span class=\"comment\">// ... but you may know better than me</span>\n</code></pre>\n\n<p>If the view returns the event back to you, your view will begin getting touchesDragged events and\nwill receive touchEnd when the touch ends (you will not receive another touchStart event, however). \nOtherwise, your view will receive a touchCancelled when the touch ends.</p>","errors":[],"demos":{},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Touch Events"}
View
42 docs/build/articles/touch/releasing.html
@@ -89,4 +89,46 @@
</head><body><div class="header"><a href="../../index.html" class="img"><img src="../../resources/logo.png" /></a><a href="../../index.html" class="here">Documentation
</a><a href="../../reference/index.html" class="item">SproutCore Reference
</a></div><div class="content"><h1>Releasing</h1>
+
+<p>Why would you want to give up a touch? Imagine that your control is inside a <code class='syntax js'><span class="class">SC</span>.<span class="class">ScrollView</span></code>:
+if the touch moves too much, perhaps it should be considered a scroll, rather than an
+action for your control.</p>
+
+<p>From touchesDragged, you would give up touch responder status through a line like this:</p>
+
+<pre><code class='syntax js'><span class="variable">someTouch</span>.<span class="variable">makeTouchResponder</span>(<span class="variable">someTouch</span>.<span class="variable">nextTouchResponder</span>);
+</code></pre>
+
+<p>The touch's nextTouchResponder is the responder that is the <em>parent</em> touch responder; through
+devious trickery (see <em>Capturing Touches</em>), ScrollView receives touch responder status <em>before</em>
+other views; further, it doesn't just hand touch responder status to the target view (your view)--
+it adds the responder to a stack of touch responders for the touch, so the responders can easily
+return to their parent responder (which is what you do with the above line of code.)</p>
+
+<p>Remember, though, that touchesDragged is called with a set of touches. It is really easy
+to change the responder for all of the touches simultaneously, should you wish to do so:</p>
+
+<pre><code class='syntax js'><span class="variable">touches</span>.<span class="variable">forEach</span>(<span class="keyword">function</span>(<span class="variable">touch</span>){
+ <span class="variable">touch</span>.<span class="variable">makeTouchResponder</span>(<span class="variable">touch</span>.<span class="variable">nextTouchResponder</span>);
+});
+</code></pre>
+
+<p>Perhaps you want to pass control only if the responder is scrollable:</p>
+
+<pre><code class='syntax js'><span class="keyword">if</span> (<span class="variable">touch</span>.<span class="variable">nextTouchResponder</span> &amp;&amp; <span class="variable">touch</span>.<span class="variable">nextTouchResponder</span>.<span class="variable">isScrollable</span>) {
+ <span class="variable">touch</span>.<span class="variable">makeTouchResponder</span>(<span class="variable">touch</span>.<span class="variable">nextTouchResponder</span>);
+}
+</code></pre>
+
+<p><code class='syntax js'><span class="variable">touchCancelled</span></code> will be called on your view automatically.</p>
+
+<h2>What Does It Look Like?</h2>
+
+<p>In this example, there is a single white box, containing a gray inner box. When you press
+on the inner box, the outer box will capture the touch first. After a delay, it re-captures
+by calling captureTouch, and the inner view receives it. This is just like the "Capturing" demo.</p>
+
+<p>However, the inner view, after a second, will release it back.</p>
+
+<p><a href='releasing.js' class='demo'>releasing.js</a></p>
</div><div class="footer"></div></body></html>
View
88 docs/build/articles/touch/releasing.js
@@ -0,0 +1,88 @@
+/**
+ This is similar to the "Capturing" example.
+
+ In fact, the outer view is identical. Only the inner view has changed.
+ As we can't pass control back without stacking, this demo _only_ includes
+ the stacking method.
+
+ The inner view, just like the outer view, passes control back after a specific
+ time period.
+*/
+var Tester = SC.View.extend({
+ backgroundColor: "white",
+
+ captureTouch: function() {
+ return YES;
+ },
+
+ touchStart: function(touch) {
+ this._hasTouch = touch;
+ this.get("layer").style.backgroundColor = "red";
+
+ // in one second, we'll pass the touch along.
+ this.invokeLater("beginContentTouches", 1000, touch);
+ return YES;
+ },
+
+ beginContentTouches: function(touch) {
+ // if our touch hasn't changed in the meantime
+ if (touch === this._hasTouch) {
+ // we'll pass the touch along.
+ touch.captureTouch(this, YES);
+ }
+ },
+
+ touchEnd: function(touch) {
+ this._hasTouch = NO;
+ this.get("layer").style.backgroundColor = "white";
+ },
+
+ touchCancelled: function(touch) {
+ this._hasTouch = NO;
+ this.get("layer").style.backgroundColor = "white";
+ },
+
+ childViews: "inner".w(),
+ inner: SC.View.design({
+ layout: { left: 50, top: 50, right: 50, bottom: 50 },
+ backgroundColor: "gray",
+ touchStart: function(touch) {
+ this._touch = touch;
+ this.get("layer").style.backgroundColor = "blue";
+ this.invokeLater("releaseTouch", 1000, touch);
+ return YES;
+ },
+
+ releaseTouch: function(touch) {
+ if (touch === this._touch) {
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ }
+ },
+
+ touchEnd: function(touch) {
+ this._touch = NO;
+ this.get("layer").style.backgroundColor = "gray";
+ },
+
+ touchCancelled: function(touch) {
+ this._touch = NO;
+ this.get("layer").style.backgroundColor = "gray";
+ }
+
+ })
+
+});
+
+var MyExampleView = SC.View.extend({
+ backgroundColor: "#aaa",
+ childViews: "demo".w(),
+ demo: Tester.extend({
+ layout: { top: 10, left: 10, width: 200, height: 200 },
+ shouldStack: YES
+ })
+});
+
+// bootstrap code :)
+exports.getDemoView = function() {
+ return MyExampleView;
+};
View
2  docs/build/articles/touch/releasing.json
@@ -1 +1 @@
-{"content":"<h1>Releasing</h1>","errors":[],"demos":{},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Releasing"}
+{"content":"<h1>Releasing</h1>\n\n<p>Why would you want to give up a touch? Imagine that your control is inside a <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">ScrollView</span></code>:\nif the touch moves too much, perhaps it should be considered a scroll, rather than an\naction for your control.</p>\n\n<p>From touchesDragged, you would give up touch responder status through a line like this:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">someTouch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">someTouch</span>.<span class=\"variable\">nextTouchResponder</span>);\n</code></pre>\n\n<p>The touch's nextTouchResponder is the responder that is the <em>parent</em> touch responder; through\ndevious trickery (see <em>Capturing Touches</em>), ScrollView receives touch responder status <em>before</em>\nother views; further, it doesn't just hand touch responder status to the target view (your view)--\nit adds the responder to a stack of touch responders for the touch, so the responders can easily\nreturn to their parent responder (which is what you do with the above line of code.)</p>\n\n<p>Remember, though, that touchesDragged is called with a set of touches. It is really easy\nto change the responder for all of the touches simultaneously, should you wish to do so:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touches</span>.<span class=\"variable\">forEach</span>(<span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>){\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n});\n</code></pre>\n\n<p>Perhaps you want to pass control only if the responder is scrollable:</p>\n\n<pre><code class='syntax js'><span class=\"keyword\">if</span> (<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span> &amp;&amp; <span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>.<span class=\"variable\">isScrollable</span>) {\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n}\n</code></pre>\n\n<p><code class='syntax js'><span class=\"variable\">touchCancelled</span></code> will be called on your view automatically.</p>\n\n<h2>What Does It Look Like?</h2>\n\n<p>In this example, there is a single white box, containing a gray inner box. When you press\non the inner box, the outer box will capture the touch first. After a delay, it re-captures\nby calling captureTouch, and the inner view receives it. This is just like the \"Capturing\" demo.</p>\n\n<p>However, the inner view, after a second, will release it back.</p>\n\n<p><a href='releasing.js' class='demo'>releasing.js</a></p>","errors":[],"demos":{"releasing.js":{"ex":"/**\n This is similar to the \"Capturing\" example.\n \n In fact, the outer view is identical. Only the inner view has changed.\n As we can't pass control back without stacking, this demo _only_ includes\n the stacking method.\n \n The inner view, just like the outer view, passes control back after a specific\n time period.\n*/\nvar Tester = SC.View.extend({\n backgroundColor: \"white\",\n \n captureTouch: function() {\n return YES;\n },\n \n touchStart: function(touch) {\n this._hasTouch = touch;\n this.get(\"layer\").style.backgroundColor = \"red\";\n \n // in one second, we'll pass the touch along.\n this.invokeLater(\"beginContentTouches\", 1000, touch);\n return YES;\n },\n \n beginContentTouches: function(touch) {\n // if our touch hasn't changed in the meantime\n if (touch === this._hasTouch) {\n // we'll pass the touch along.\n touch.captureTouch(this, YES);\n }\n },\n \n touchEnd: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n touchCancelled: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n childViews: \"inner\".w(),\n inner: SC.View.design({\n layout: { left: 50, top: 50, right: 50, bottom: 50 },\n backgroundColor: \"gray\",\n touchStart: function(touch) {\n this._touch = touch;\n this.get(\"layer\").style.backgroundColor = \"blue\";\n this.invokeLater(\"releaseTouch\", 1000, touch);\n return YES;\n },\n \n releaseTouch: function(touch) {\n if (touch === this._touch) {\n touch.makeTouchResponder(touch.nextTouchResponder);\n }\n },\n \n touchEnd: function(touch) {\n this._touch = NO;\n this.get(\"layer\").style.backgroundColor = \"gray\";\n },\n \n touchCancelled: function(touch) {\n this._touch = NO;\n this.get(\"layer\").style.backgroundColor = \"gray\";\n }\n \n })\n \n});\n\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"#aaa\",\n childViews: \"demo\".w(),\n demo: Tester.extend({\n layout: { top: 10, left: 10, width: 200, height: 200 },\n shouldStack: YES\n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n","highlighted":"<span class=\"multiline comment\">/**\n This is similar to the &quot;Capturing&quot; example.\n \n In fact, the outer view is identical. Only the inner view has changed.\n As we can't pass control back without stacking, this demo _only_ includes\n the stacking method.\n \n The inner view, just like the outer view, passes control back after a specific\n time period.\n*/</span>\n<span class=\"keyword\">var</span> <span class=\"class\">Tester</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;white&quot;</span>,\n \n <span class=\"variable\">captureTouch</span>: <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"variable\">touch</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;red&quot;</span>;\n \n <span class=\"comment\">// in one second, we'll pass the touch along.</span>\n <span class=\"this\">this</span>.<span class=\"variable\">invokeLater</span>(<span class=\"string\">&quot;beginContentTouches&quot;</span>, <span class=\"number integer\">1000</span>, <span class=\"variable\">touch</span>);\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">beginContentTouches</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"comment\">// if our touch hasn't changed in the meantime</span>\n <span class=\"keyword\">if</span> (<span class=\"variable\">touch</span> === <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span>) {\n <span class=\"comment\">// we'll pass the touch along.</span>\n <span class=\"variable\">touch</span>.<span class=\"variable\">captureTouch</span>(<span class=\"this\">this</span>, <span class=\"class\">YES</span>);\n }\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;white&quot;</span>;\n },\n \n <span class=\"variable\">touchCancelled</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_hasTouch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;white&quot;</span>;\n },\n \n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;inner&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">inner</span>: <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">left</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">top</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">right</span>: <span class=\"number integer\">50</span>, <span class=\"variable\">bottom</span>: <span class=\"number integer\">50</span> },\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;gray&quot;</span>,\n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_touch</span> = <span class=\"variable\">touch</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;blue&quot;</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">invokeLater</span>(<span class=\"string\">&quot;releaseTouch&quot;</span>, <span class=\"number integer\">1000</span>, <span class=\"variable\">touch</span>);\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>;\n },\n \n <span class=\"variable\">releaseTouch</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"keyword\">if</span> (<span class=\"variable\">touch</span> === <span class=\"this\">this</span>.<span class=\"variable\">_touch</span>) {\n <span class=\"variable\">touch</span>.<span class=\"variable\">makeTouchResponder</span>(<span class=\"variable\">touch</span>.<span class=\"variable\">nextTouchResponder</span>);\n }\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_touch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;gray&quot;</span>;\n },\n \n <span class=\"variable\">touchCancelled</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">_touch</span> = <span class=\"class\">NO</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;layer&quot;</span>).<span class=\"variable\">style</span>.<span class=\"variable\">backgroundColor</span> = <span class=\"string\">&quot;gray&quot;</span>;\n }\n \n })\n \n});\n\n<span class=\"keyword\">var</span> <span class=\"class\">MyExampleView</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;#aaa&quot;</span>,\n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;demo&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">demo</span>: <span class=\"class\">Tester</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">layout</span>: { <span class=\"variable\">top</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">200</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">200</span> },\n <span class=\"variable\">shouldStack</span>: <span class=\"class\">YES</span>\n })\n});\n\n<span class=\"comment\">// bootstrap code :)</span>\n<span class=\"variable\">exports</span>.<span class=\"variable\">getDemoView</span> = <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">MyExampleView</span>;\n};\n","original":"/**\n This is similar to the \"Capturing\" example.\n \n In fact, the outer view is identical. Only the inner view has changed.\n As we can't pass control back without stacking, this demo _only_ includes\n the stacking method.\n \n The inner view, just like the outer view, passes control back after a specific\n time period.\n*/\nvar Tester = SC.View.extend({\n backgroundColor: \"white\",\n \n captureTouch: function() {\n return YES;\n },\n \n touchStart: function(touch) {\n this._hasTouch = touch;\n this.get(\"layer\").style.backgroundColor = \"red\";\n \n // in one second, we'll pass the touch along.\n this.invokeLater(\"beginContentTouches\", 1000, touch);\n return YES;\n },\n \n beginContentTouches: function(touch) {\n // if our touch hasn't changed in the meantime\n if (touch === this._hasTouch) {\n // we'll pass the touch along.\n touch.captureTouch(this, YES);\n }\n },\n \n touchEnd: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n touchCancelled: function(touch) {\n this._hasTouch = NO;\n this.get(\"layer\").style.backgroundColor = \"white\";\n },\n \n childViews: \"inner\".w(),\n inner: SC.View.design({\n layout: { left: 50, top: 50, right: 50, bottom: 50 },\n backgroundColor: \"gray\",\n touchStart: function(touch) {\n this._touch = touch;\n this.get(\"layer\").style.backgroundColor = \"blue\";\n this.invokeLater(\"releaseTouch\", 1000, touch);\n return YES;\n },\n \n releaseTouch: function(touch) {\n if (touch === this._touch) {\n touch.makeTouchResponder(touch.nextTouchResponder);\n }\n },\n \n touchEnd: function(touch) {\n this._touch = NO;\n this.get(\"layer\").style.backgroundColor = \"gray\";\n },\n \n touchCancelled: function(touch) {\n this._touch = NO;\n this.get(\"layer\").style.backgroundColor = \"gray\";\n }\n \n })\n \n});\n\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"#aaa\",\n childViews: \"demo\".w(),\n demo: Tester.extend({\n layout: { top: 10, left: 10, width: 200, height: 200 },\n shouldStack: YES\n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n"}},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Releasing"}
View
43 docs/build/articles/touch/releasing.md
@@ -1,2 +1,43 @@
Releasing
-=========
+=========
+Why would you want to give up a touch? Imagine that your control is inside a `#js:SC.ScrollView`:
+if the touch moves too much, perhaps it should be considered a scroll, rather than an
+action for your control.
+
+From touchesDragged, you would give up touch responder status through a line like this:
+
+ #js
+ someTouch.makeTouchResponder(someTouch.nextTouchResponder);
+
+The touch's nextTouchResponder is the responder that is the _parent_ touch responder; through
+devious trickery (see *Capturing Touches*), ScrollView receives touch responder status _before_
+other views; further, it doesn't just hand touch responder status to the target view (your view)--
+it adds the responder to a stack of touch responders for the touch, so the responders can easily
+return to their parent responder (which is what you do with the above line of code.)
+
+Remember, though, that touchesDragged is called with a set of touches. It is really easy
+to change the responder for all of the touches simultaneously, should you wish to do so:
+
+ #js
+ touches.forEach(function(touch){
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ });
+
+Perhaps you want to pass control only if the responder is scrollable:
+
+ #js
+ if (touch.nextTouchResponder && touch.nextTouchResponder.isScrollable) {
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ }
+
+`#js:touchCancelled` will be called on your view automatically.
+
+What Does It Look Like?
+-----------------------
+In this example, there is a single white box, containing a gray inner box. When you press
+on the inner box, the outer box will capture the touch first. After a delay, it re-captures
+by calling captureTouch, and the inner view receives it. This is just like the "Capturing" demo.
+
+However, the inner view, after a second, will release it back.
+
+{{demo:sc|releasing.js}}
View
8 docs/build/articles/touch/touch-events.html
@@ -117,7 +117,7 @@
</code></pre>
<p>Instead of being passed a raw event, <code class='syntax js'><span class="variable">touchStart</span></code> is passed an <code class='syntax js'><span class="class">SC</span>.<span class="class">Touch</span></code> object.
-If you return YES from touchStart, your view will "own" the touchin SproutCore terms, your
+If you return YES from touchStart, your view will "own" the touch&emdash;in SproutCore terms, your
view will be the <em>touch responder</em>. For more information about what this entails, see
the "Internals" article. Your view will own the touch until the touch ends.</p>
@@ -125,7 +125,7 @@
<p><strong>Note:</strong> By default, views only receive <code class='syntax js'><span class="variable">touchStart</span></code> and touchEnd for a single touch. This is
a feature intended to make it easier to handle such cases, very similar to Cocoa Touch's <code class='syntax js'><span class="variable">acceptsMultitouch</span></code>
-propertyactually, SC.View uses the same property name! See the "Multitouch" article.</p>
+property&emdash;actually, SC.View uses the same property name! See the "Multitouch" article.</p>
<h2>Anatomy of an SC.Touch</h2>
@@ -159,7 +159,7 @@
<p>It works exactly like <code class='syntax js'><span class="variable">touchStart</span></code>. The touch will no longer be in the set of touches for the view,
so if you call <code class='syntax js'><span class="variable">touch</span>.<span class="variable">touchesForView</span>(<span class="this">this</span>)</code>, you'll only receive any other active touches. If your
-view does not accept multitouch, then the set is guaranteed to have no touches in ityou only receive
+view does not accept multitouch, then the set is guaranteed to have no touches in it&emdash;you only receive
<code class='syntax js'><span class="variable">touchEnd</span></code> for the last touch that ends.</p>
<h2>Tracking Touches</h2>
@@ -169,7 +169,7 @@
<pre><code class='syntax js'><span class="variable">touchesDragged</span>: <span class="keyword">function</span>(<span class="variable">evt</span>, <span class="variable">touches</span>)
</code></pre>
-<p>The <code class='syntax js'><span class="variable">touches</span></code> argument is the set of touches on the viewthe same set you get by calling <code class='syntax js'><span class="variable">touchesForView</span>(<span class="this">this</span>)</code>.
+<p>The <code class='syntax js'><span class="variable">touches</span></code> argument is the set of touches on the view&emdash;the same set you get by calling <code class='syntax js'><span class="variable">touchesForView</span>(<span class="this">this</span>)</code>.
This will have <em>all</em> touches, regardless of whether or not your view accepts multitouch.</p>
<p>If your view does <em>not</em> accept multitouch, then it is even simpler:</p>
View
2  docs/build/articles/touch/touch-events.json
@@ -1 +1 @@
-{"content":"<h1>Touch Events</h1>\n\n<p>SproutCore's touch events have a few great features:</p>\n\n<ul>\n<li>Multiple views can receive touches simultaneously.</li>\n<li>A single view can receive multiple touches.</li>\n<li>A view can capture touches before allowing them to pass through to children.</li>\n<li>Child views can release touches back to parent views that originally captured them.</li>\n</ul>\n\n<p>We won't get into the last two in this article&emdash;they're quite sophisticated!</p>\n\n<h1>Simple Single-Touch Handling</h1>\n\n<p>You may be familiar with this SC.View method signature if you are familiar with SproutCore:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>)\n</code></pre>\n\n<p>With <code class='syntax js'><span class=\"variable\">mouseDown</span></code>, you can decide whether or not to accept the mouse event by returning either\n<code class='syntax js'><span class=\"class\">YES</span></code> or <code class='syntax js'><span class=\"class\">NO</span></code>.</p>\n\n<p>Touch events are similar, but work a bit differently:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>)\n</code></pre>\n\n<p>Instead of being passed a raw event, <code class='syntax js'><span class=\"variable\">touchStart</span></code> is passed an <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> object.\nIf you return YES from touchStart, your view will \"own\" the touch\u2014in SproutCore terms, your\nview will be the <em>touch responder</em>. For more information about what this entails, see\nthe \"Internals\" article. Your view will own the touch until the touch ends.</p>\n\n<p><code class='syntax js'><span class=\"variable\">touchStart</span></code> will be called once for every touch that touches the view.</p>\n\n<p><strong>Note:</strong> By default, views only receive <code class='syntax js'><span class=\"variable\">touchStart</span></code> and touchEnd for a single touch. This is\na feature intended to make it easier to handle such cases, very similar to Cocoa Touch's <code class='syntax js'><span class=\"variable\">acceptsMultitouch</span></code>\nproperty\u2014actually, SC.View uses the same property name! See the \"Multitouch\" article.</p>\n\n<h2>Anatomy of an SC.Touch</h2>\n\n<p>SC.Touch represents the touch from the time the user puts their finger on the screen until the time they lift it.</p>\n\n<p>The touch object acts like an event object in many ways. It has many other useful things, as well:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> for the touch</li>\n<li><code class='syntax js'><span class=\"variable\">event</span></code>: if in an event cycle, this contains the event. Otherwise, it is <code class='syntax js'><span class=\"variable\">undefined</span></code>. \nYou will probably never need to access this.</li>\n<li><code class='syntax js'><span class=\"variable\">preventDefault</span></code>: if the touch is connected with an event, this calls <code class='syntax js'><span class=\"variable\">preventDefault</span>()</code> on the event.</li>\n<li><code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"variable\">view</span>)</code>: when supplied a view, will find all touches that the view is the\ntouch responder for. It is a CoreSet; to get an array, call <code class='syntax js'>.<span class=\"variable\">toArray</span></code> on the result.</li>\n<li><code class='syntax js'><span class=\"variable\">averagedTouchesForView</span>(<span class=\"variable\">view</span>)</code>: When supplied a view, averages all the touches on that view,\nreturning both an average position and an average distance from that position.</li>\n</ul>\n\n<p><strong>Note:</strong> If you call <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code> from <code class='syntax js'><span class=\"variable\">touchStart</span></code>, the touch supplied will not be in the set\nreturned by <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>: you don't own the touch until you return YES.</p>\n\n<h2>touchEnd</h2>\n\n<p>Knowing when the touch starts is not very useful. At the very least, you will likely want to know when the touch\nends as well.</p>\n\n<p>It is quite simple:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>)\n</code></pre>\n\n<p>It works exactly like <code class='syntax js'><span class=\"variable\">touchStart</span></code>. The touch will no longer be in the set of touches for the view,\nso if you call <code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>, you'll only receive any other active touches. If your\nview does not accept multitouch, then the set is guaranteed to have no touches in it\u2014you only receive\n<code class='syntax js'><span class=\"variable\">touchEnd</span></code> for the last touch that ends.</p>\n\n<h2>Tracking Touches</h2>\n\n<p>Tracking touch movement is simple:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchesDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>, <span class=\"variable\">touches</span>)\n</code></pre>\n\n<p>The <code class='syntax js'><span class=\"variable\">touches</span></code> argument is the set of touches on the view\u2014the same set you get by calling <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>.\nThis will have <em>all</em> touches, regardless of whether or not your view accepts multitouch.</p>\n\n<p>If your view does <em>not</em> accept multitouch, then it is even simpler:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">x</span> = <span class=\"variable\">evt</span>.<span class=\"variable\">pageX</span>;\n<span class=\"variable\">y</span> = <span class=\"variable\">evt</span>.<span class=\"variable\">pageY</span>;\n</code></pre>\n\n<h2>Tip: Cross-Platform-iness</h2>\n\n<p>Did you realize that, assuming you don't use the set of view touches or other touch-specific API,\nyou can do this:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchStart</span>(<span class=\"variable\">evt</span>);\n},\n\n<span class=\"variable\">mouseDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchesDragged</span>(<span class=\"variable\">evt</span>);\n},\n\n<span class=\"variable\">mouseUp</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchEnd</span>(<span class=\"variable\">evt</span>);\n}\n</code></pre>\n\n<p>Of course, you can also redirect touch events to mouse events, but that is not as fun.</p>\n\n<h2>Putting it All Together</h2>\n\n<p>Here is a very simple demo that uses the methods described above to allow the user to move two views\naround the screen:</p>\n\n<p><a href='touch-demo.js' class='demo'>touch-demo.js</a></p>","errors":[],"demos":{"touch-demo.js":{"ex":"var Dot = SC.View.extend({\n touchStart: function(touch) {\n var f = this.get(\"frame\");\n this._touch = {\n start: { x: touch.pageX, y: touch.pageY },\n ourStart: { x: f.x, y: f.y, width: f.width, height: f.height }\n };\n return YES; // or we won't get touchesDragged\n },\n \n touchesDragged: function(evt, touches) {\n var t = this._touch;\n this.set(\"layout\", { \n left: t.ourStart.x + evt.pageX - t.start.x,\n top: t.ourStart.y + evt.pageY - t.start.y,\n width: t.ourStart.width,\n height: t.ourStart.height\n });\n },\n \n touchEnd: function() {\n // actually, we don't need to do anything here...\n },\n \n // and now, redirect mouse events :)\n mouseDown: function(evt) {\n this.touchStart(evt);\n },\n \n mouseDragged: function(evt) {\n this.touchesDragged(evt);\n },\n \n mouseUp: function(evt) {\n this.touchEnd(evt);\n }\n});\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"white\",\n childViews: \"dot1 dot2\".w(),\n dot1: Dot.design({\n backgroundColor: \"red\",\n layout: { left: 10, top: 10, width: 100, height: 100 }\n }),\n dot2: Dot.design({\n backgroundColor: \"blue\",\n layout: { right: 10, bottom: 10, width: 100, height: 100 }\n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n","highlighted":"<span class=\"keyword\">var</span> <span class=\"class\">Dot</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"keyword\">var</span> <span class=\"variable\">f</span> = <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;frame&quot;</span>);\n <span class=\"this\">this</span>.<span class=\"variable\">_touch</span> = {\n <span class=\"variable\">start</span>: { <span class=\"variable\">x</span>: <span class=\"variable\">touch</span>.<span class=\"variable\">pageX</span>, <span class=\"variable\">y</span>: <span class=\"variable\">touch</span>.<span class=\"variable\">pageY</span> },\n <span class=\"variable\">ourStart</span>: { <span class=\"variable\">x</span>: <span class=\"variable\">f</span>.<span class=\"variable\">x</span>, <span class=\"variable\">y</span>: <span class=\"variable\">f</span>.<span class=\"variable\">y</span>, <span class=\"variable\">width</span>: <span class=\"variable\">f</span>.<span class=\"variable\">width</span>, <span class=\"variable\">height</span>: <span class=\"variable\">f</span>.<span class=\"variable\">height</span> }\n };\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>; <span class=\"comment\">// or we won't get touchesDragged</span>\n },\n \n <span class=\"variable\">touchesDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>, <span class=\"variable\">touches</span>) {\n <span class=\"keyword\">var</span> <span class=\"variable\">t</span> = <span class=\"this\">this</span>.<span class=\"variable\">_touch</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">set</span>(<span class=\"string\">&quot;layout&quot;</span>, { \n <span class=\"variable\">left</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">x</span> + <span class=\"variable\">evt</span>.<span class=\"variable\">pageX</span> - <span class=\"variable\">t</span>.<span class=\"variable\">start</span>.<span class=\"variable\">x</span>,\n <span class=\"variable\">top</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">y</span> + <span class=\"variable\">evt</span>.<span class=\"variable\">pageY</span> - <span class=\"variable\">t</span>.<span class=\"variable\">start</span>.<span class=\"variable\">y</span>,\n <span class=\"variable\">width</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">width</span>,\n <span class=\"variable\">height</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">height</span>\n });\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>() {\n <span class=\"comment\">// actually, we don't need to do anything here...</span>\n },\n \n <span class=\"comment\">// and now, redirect mouse events :)</span>\n <span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchStart</span>(<span class=\"variable\">evt</span>);\n },\n \n <span class=\"variable\">mouseDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchesDragged</span>(<span class=\"variable\">evt</span>);\n },\n \n <span class=\"variable\">mouseUp</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchEnd</span>(<span class=\"variable\">evt</span>);\n }\n});\n<span class=\"keyword\">var</span> <span class=\"class\">MyExampleView</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;white&quot;</span>,\n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;dot1 dot2&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">dot1</span>: <span class=\"class\">Dot</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;red&quot;</span>,\n <span class=\"variable\">layout</span>: { <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">top</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">100</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">100</span> }\n }),\n <span class=\"variable\">dot2</span>: <span class=\"class\">Dot</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;blue&quot;</span>,\n <span class=\"variable\">layout</span>: { <span class=\"variable\">right</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">bottom</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">100</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">100</span> }\n })\n});\n\n<span class=\"comment\">// bootstrap code :)</span>\n<span class=\"variable\">exports</span>.<span class=\"variable\">getDemoView</span> = <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">MyExampleView</span>;\n};\n","original":"var Dot = SC.View.extend({\n touchStart: function(touch) {\n var f = this.get(\"frame\");\n this._touch = {\n start: { x: touch.pageX, y: touch.pageY },\n ourStart: { x: f.x, y: f.y, width: f.width, height: f.height }\n };\n return YES; // or we won't get touchesDragged\n },\n \n touchesDragged: function(evt, touches) {\n var t = this._touch;\n this.set(\"layout\", { \n left: t.ourStart.x + evt.pageX - t.start.x,\n top: t.ourStart.y + evt.pageY - t.start.y,\n width: t.ourStart.width,\n height: t.ourStart.height\n });\n },\n \n touchEnd: function() {\n // actually, we don't need to do anything here...\n },\n \n // and now, redirect mouse events :)\n mouseDown: function(evt) {\n this.touchStart(evt);\n },\n \n mouseDragged: function(evt) {\n this.touchesDragged(evt);\n },\n \n mouseUp: function(evt) {\n this.touchEnd(evt);\n }\n});\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"white\",\n childViews: \"dot1 dot2\".w(),\n dot1: Dot.design({\n backgroundColor: \"red\",\n layout: { left: 10, top: 10, width: 100, height: 100 }\n }),\n dot2: Dot.design({\n backgroundColor: \"blue\",\n layout: { right: 10, bottom: 10, width: 100, height: 100 }\n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n"}},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Touch Events"}
+{"content":"<h1>Touch Events</h1>\n\n<p>SproutCore's touch events have a few great features:</p>\n\n<ul>\n<li>Multiple views can receive touches simultaneously.</li>\n<li>A single view can receive multiple touches.</li>\n<li>A view can capture touches before allowing them to pass through to children.</li>\n<li>Child views can release touches back to parent views that originally captured them.</li>\n</ul>\n\n<p>We won't get into the last two in this article&emdash;they're quite sophisticated!</p>\n\n<h1>Simple Single-Touch Handling</h1>\n\n<p>You may be familiar with this SC.View method signature if you are familiar with SproutCore:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>)\n</code></pre>\n\n<p>With <code class='syntax js'><span class=\"variable\">mouseDown</span></code>, you can decide whether or not to accept the mouse event by returning either\n<code class='syntax js'><span class=\"class\">YES</span></code> or <code class='syntax js'><span class=\"class\">NO</span></code>.</p>\n\n<p>Touch events are similar, but work a bit differently:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>)\n</code></pre>\n\n<p>Instead of being passed a raw event, <code class='syntax js'><span class=\"variable\">touchStart</span></code> is passed an <code class='syntax js'><span class=\"class\">SC</span>.<span class=\"class\">Touch</span></code> object.\nIf you return YES from touchStart, your view will \"own\" the touch&emdash;in SproutCore terms, your\nview will be the <em>touch responder</em>. For more information about what this entails, see\nthe \"Internals\" article. Your view will own the touch until the touch ends.</p>\n\n<p><code class='syntax js'><span class=\"variable\">touchStart</span></code> will be called once for every touch that touches the view.</p>\n\n<p><strong>Note:</strong> By default, views only receive <code class='syntax js'><span class=\"variable\">touchStart</span></code> and touchEnd for a single touch. This is\na feature intended to make it easier to handle such cases, very similar to Cocoa Touch's <code class='syntax js'><span class=\"variable\">acceptsMultitouch</span></code>\nproperty&emdash;actually, SC.View uses the same property name! See the \"Multitouch\" article.</p>\n\n<h2>Anatomy of an SC.Touch</h2>\n\n<p>SC.Touch represents the touch from the time the user puts their finger on the screen until the time they lift it.</p>\n\n<p>The touch object acts like an event object in many ways. It has many other useful things, as well:</p>\n\n<ul>\n<li><code class='syntax js'><span class=\"variable\">pageX</span></code> and <code class='syntax js'><span class=\"variable\">pageY</span></code> for the touch</li>\n<li><code class='syntax js'><span class=\"variable\">event</span></code>: if in an event cycle, this contains the event. Otherwise, it is <code class='syntax js'><span class=\"variable\">undefined</span></code>. \nYou will probably never need to access this.</li>\n<li><code class='syntax js'><span class=\"variable\">preventDefault</span></code>: if the touch is connected with an event, this calls <code class='syntax js'><span class=\"variable\">preventDefault</span>()</code> on the event.</li>\n<li><code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"variable\">view</span>)</code>: when supplied a view, will find all touches that the view is the\ntouch responder for. It is a CoreSet; to get an array, call <code class='syntax js'>.<span class=\"variable\">toArray</span></code> on the result.</li>\n<li><code class='syntax js'><span class=\"variable\">averagedTouchesForView</span>(<span class=\"variable\">view</span>)</code>: When supplied a view, averages all the touches on that view,\nreturning both an average position and an average distance from that position.</li>\n</ul>\n\n<p><strong>Note:</strong> If you call <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code> from <code class='syntax js'><span class=\"variable\">touchStart</span></code>, the touch supplied will not be in the set\nreturned by <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>: you don't own the touch until you return YES.</p>\n\n<h2>touchEnd</h2>\n\n<p>Knowing when the touch starts is not very useful. At the very least, you will likely want to know when the touch\nends as well.</p>\n\n<p>It is quite simple:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>)\n</code></pre>\n\n<p>It works exactly like <code class='syntax js'><span class=\"variable\">touchStart</span></code>. The touch will no longer be in the set of touches for the view,\nso if you call <code class='syntax js'><span class=\"variable\">touch</span>.<span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>, you'll only receive any other active touches. If your\nview does not accept multitouch, then the set is guaranteed to have no touches in it&emdash;you only receive\n<code class='syntax js'><span class=\"variable\">touchEnd</span></code> for the last touch that ends.</p>\n\n<h2>Tracking Touches</h2>\n\n<p>Tracking touch movement is simple:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">touchesDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>, <span class=\"variable\">touches</span>)\n</code></pre>\n\n<p>The <code class='syntax js'><span class=\"variable\">touches</span></code> argument is the set of touches on the view&emdash;the same set you get by calling <code class='syntax js'><span class=\"variable\">touchesForView</span>(<span class=\"this\">this</span>)</code>.\nThis will have <em>all</em> touches, regardless of whether or not your view accepts multitouch.</p>\n\n<p>If your view does <em>not</em> accept multitouch, then it is even simpler:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">x</span> = <span class=\"variable\">evt</span>.<span class=\"variable\">pageX</span>;\n<span class=\"variable\">y</span> = <span class=\"variable\">evt</span>.<span class=\"variable\">pageY</span>;\n</code></pre>\n\n<h2>Tip: Cross-Platform-iness</h2>\n\n<p>Did you realize that, assuming you don't use the set of view touches or other touch-specific API,\nyou can do this:</p>\n\n<pre><code class='syntax js'><span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchStart</span>(<span class=\"variable\">evt</span>);\n},\n\n<span class=\"variable\">mouseDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchesDragged</span>(<span class=\"variable\">evt</span>);\n},\n\n<span class=\"variable\">mouseUp</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchEnd</span>(<span class=\"variable\">evt</span>);\n}\n</code></pre>\n\n<p>Of course, you can also redirect touch events to mouse events, but that is not as fun.</p>\n\n<h2>Putting it All Together</h2>\n\n<p>Here is a very simple demo that uses the methods described above to allow the user to move two views\naround the screen:</p>\n\n<p><a href='touch-demo.js' class='demo'>touch-demo.js</a></p>","errors":[],"demos":{"touch-demo.js":{"ex":"var Dot = SC.View.extend({\n touchStart: function(touch) {\n var f = this.get(\"frame\");\n this._touch = {\n start: { x: touch.pageX, y: touch.pageY },\n ourStart: { x: f.x, y: f.y, width: f.width, height: f.height }\n };\n return YES; // or we won't get touchesDragged\n },\n \n touchesDragged: function(evt, touches) {\n var t = this._touch;\n this.set(\"layout\", { \n left: t.ourStart.x + evt.pageX - t.start.x,\n top: t.ourStart.y + evt.pageY - t.start.y,\n width: t.ourStart.width,\n height: t.ourStart.height\n });\n },\n \n touchEnd: function() {\n // actually, we don't need to do anything here...\n },\n \n // and now, redirect mouse events :)\n mouseDown: function(evt) {\n this.touchStart(evt);\n },\n \n mouseDragged: function(evt) {\n this.touchesDragged(evt);\n },\n \n mouseUp: function(evt) {\n this.touchEnd(evt);\n }\n});\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"white\",\n childViews: \"dot1 dot2\".w(),\n dot1: Dot.design({\n backgroundColor: \"red\",\n layout: { left: 10, top: 10, width: 100, height: 100 }\n }),\n dot2: Dot.design({\n backgroundColor: \"blue\",\n layout: { right: 10, bottom: 10, width: 100, height: 100 }\n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n","highlighted":"<span class=\"keyword\">var</span> <span class=\"class\">Dot</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">touchStart</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">touch</span>) {\n <span class=\"keyword\">var</span> <span class=\"variable\">f</span> = <span class=\"this\">this</span>.<span class=\"variable\">get</span>(<span class=\"string\">&quot;frame&quot;</span>);\n <span class=\"this\">this</span>.<span class=\"variable\">_touch</span> = {\n <span class=\"variable\">start</span>: { <span class=\"variable\">x</span>: <span class=\"variable\">touch</span>.<span class=\"variable\">pageX</span>, <span class=\"variable\">y</span>: <span class=\"variable\">touch</span>.<span class=\"variable\">pageY</span> },\n <span class=\"variable\">ourStart</span>: { <span class=\"variable\">x</span>: <span class=\"variable\">f</span>.<span class=\"variable\">x</span>, <span class=\"variable\">y</span>: <span class=\"variable\">f</span>.<span class=\"variable\">y</span>, <span class=\"variable\">width</span>: <span class=\"variable\">f</span>.<span class=\"variable\">width</span>, <span class=\"variable\">height</span>: <span class=\"variable\">f</span>.<span class=\"variable\">height</span> }\n };\n <span class=\"keyword\">return</span> <span class=\"class\">YES</span>; <span class=\"comment\">// or we won't get touchesDragged</span>\n },\n \n <span class=\"variable\">touchesDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>, <span class=\"variable\">touches</span>) {\n <span class=\"keyword\">var</span> <span class=\"variable\">t</span> = <span class=\"this\">this</span>.<span class=\"variable\">_touch</span>;\n <span class=\"this\">this</span>.<span class=\"variable\">set</span>(<span class=\"string\">&quot;layout&quot;</span>, { \n <span class=\"variable\">left</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">x</span> + <span class=\"variable\">evt</span>.<span class=\"variable\">pageX</span> - <span class=\"variable\">t</span>.<span class=\"variable\">start</span>.<span class=\"variable\">x</span>,\n <span class=\"variable\">top</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">y</span> + <span class=\"variable\">evt</span>.<span class=\"variable\">pageY</span> - <span class=\"variable\">t</span>.<span class=\"variable\">start</span>.<span class=\"variable\">y</span>,\n <span class=\"variable\">width</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">width</span>,\n <span class=\"variable\">height</span>: <span class=\"variable\">t</span>.<span class=\"variable\">ourStart</span>.<span class=\"variable\">height</span>\n });\n },\n \n <span class=\"variable\">touchEnd</span>: <span class=\"keyword\">function</span>() {\n <span class=\"comment\">// actually, we don't need to do anything here...</span>\n },\n \n <span class=\"comment\">// and now, redirect mouse events :)</span>\n <span class=\"variable\">mouseDown</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchStart</span>(<span class=\"variable\">evt</span>);\n },\n \n <span class=\"variable\">mouseDragged</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchesDragged</span>(<span class=\"variable\">evt</span>);\n },\n \n <span class=\"variable\">mouseUp</span>: <span class=\"keyword\">function</span>(<span class=\"variable\">evt</span>) {\n <span class=\"this\">this</span>.<span class=\"variable\">touchEnd</span>(<span class=\"variable\">evt</span>);\n }\n});\n<span class=\"keyword\">var</span> <span class=\"class\">MyExampleView</span> = <span class=\"class\">SC</span>.<span class=\"class\">View</span>.<span class=\"variable\">extend</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;white&quot;</span>,\n <span class=\"variable\">childViews</span>: <span class=\"string\">&quot;dot1 dot2&quot;</span>.<span class=\"variable\">w</span>(),\n <span class=\"variable\">dot1</span>: <span class=\"class\">Dot</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;red&quot;</span>,\n <span class=\"variable\">layout</span>: { <span class=\"variable\">left</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">top</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">100</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">100</span> }\n }),\n <span class=\"variable\">dot2</span>: <span class=\"class\">Dot</span>.<span class=\"variable\">design</span>({\n <span class=\"variable\">backgroundColor</span>: <span class=\"string\">&quot;blue&quot;</span>,\n <span class=\"variable\">layout</span>: { <span class=\"variable\">right</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">bottom</span>: <span class=\"number integer\">10</span>, <span class=\"variable\">width</span>: <span class=\"number integer\">100</span>, <span class=\"variable\">height</span>: <span class=\"number integer\">100</span> }\n })\n});\n\n<span class=\"comment\">// bootstrap code :)</span>\n<span class=\"variable\">exports</span>.<span class=\"variable\">getDemoView</span> = <span class=\"keyword\">function</span>() {\n <span class=\"keyword\">return</span> <span class=\"class\">MyExampleView</span>;\n};\n","original":"var Dot = SC.View.extend({\n touchStart: function(touch) {\n var f = this.get(\"frame\");\n this._touch = {\n start: { x: touch.pageX, y: touch.pageY },\n ourStart: { x: f.x, y: f.y, width: f.width, height: f.height }\n };\n return YES; // or we won't get touchesDragged\n },\n \n touchesDragged: function(evt, touches) {\n var t = this._touch;\n this.set(\"layout\", { \n left: t.ourStart.x + evt.pageX - t.start.x,\n top: t.ourStart.y + evt.pageY - t.start.y,\n width: t.ourStart.width,\n height: t.ourStart.height\n });\n },\n \n touchEnd: function() {\n // actually, we don't need to do anything here...\n },\n \n // and now, redirect mouse events :)\n mouseDown: function(evt) {\n this.touchStart(evt);\n },\n \n mouseDragged: function(evt) {\n this.touchesDragged(evt);\n },\n \n mouseUp: function(evt) {\n this.touchEnd(evt);\n }\n});\nvar MyExampleView = SC.View.extend({\n backgroundColor: \"white\",\n childViews: \"dot1 dot2\".w(),\n dot1: Dot.design({\n backgroundColor: \"red\",\n layout: { left: 10, top: 10, width: 100, height: 100 }\n }),\n dot2: Dot.design({\n backgroundColor: \"blue\",\n layout: { right: 10, bottom: 10, width: 100, height: 100 }\n })\n});\n\n// bootstrap code :)\nexports.getDemoView = function() {\n return MyExampleView;\n};\n"}},"articleDirectory":"articles/touch/","outputDirectory":"build/","title":"Touch Events"}
View
2  docs/build/guides/touch.json
1 addition, 1 deletion not shown
View
2  docs/src/articles/touch/capturing.js
@@ -19,6 +19,7 @@ var Tester = SC.View.extend({
// in one second, we'll pass the touch along.
this.invokeLater("beginContentTouches", 1000, touch);
+ return YES;
},
beginContentTouches: function(touch) {
@@ -45,6 +46,7 @@ var Tester = SC.View.extend({
backgroundColor: "gray",
touchStart: function() {
this.get("layer").style.backgroundColor = "blue";
+ return YES;
},
touchEnd: function() {
View
5 docs/src/articles/touch/capturing.md
@@ -61,6 +61,11 @@ What happens next depends on whether or not you told it to stack your view:
What Does It Look Like?
-----------------------
+In this example, we have two boxes, each containing an inner box. The outer boxes
+capture touches, and only pass them to the inner box after a delay. The top box stacks,
+the other one does not; this causes, as described above, a difference in when touchEnd/Cancelled
+is called on the outer boxes.
+
{{demo:sc|capturing.js}}
View
88 docs/src/articles/touch/releasing.js
@@ -0,0 +1,88 @@
+/**
+ This is similar to the "Capturing" example.
+
+ In fact, the outer view is identical. Only the inner view has changed.
+ As we can't pass control back without stacking, this demo _only_ includes
+ the stacking method.
+
+ The inner view, just like the outer view, passes control back after a specific
+ time period.
+*/
+var Tester = SC.View.extend({
+ backgroundColor: "white",
+
+ captureTouch: function() {
+ return YES;
+ },
+
+ touchStart: function(touch) {
+ this._hasTouch = touch;
+ this.get("layer").style.backgroundColor = "red";
+
+ // in one second, we'll pass the touch along.
+ this.invokeLater("beginContentTouches", 1000, touch);
+ return YES;
+ },
+
+ beginContentTouches: function(touch) {
+ // if our touch hasn't changed in the meantime
+ if (touch === this._hasTouch) {
+ // we'll pass the touch along.
+ touch.captureTouch(this, YES);
+ }
+ },
+
+ touchEnd: function(touch) {
+ this._hasTouch = NO;
+ this.get("layer").style.backgroundColor = "white";
+ },
+
+ touchCancelled: function(touch) {
+ this._hasTouch = NO;
+ this.get("layer").style.backgroundColor = "white";
+ },
+
+ childViews: "inner".w(),
+ inner: SC.View.design({
+ layout: { left: 50, top: 50, right: 50, bottom: 50 },
+ backgroundColor: "gray",
+ touchStart: function(touch) {
+ this._touch = touch;
+ this.get("layer").style.backgroundColor = "blue";
+ this.invokeLater("releaseTouch", 1000, touch);
+ return YES;
+ },
+
+ releaseTouch: function(touch) {
+ if (touch === this._touch) {
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ }
+ },
+
+ touchEnd: function(touch) {
+ this._touch = NO;
+ this.get("layer").style.backgroundColor = "gray";
+ },
+
+ touchCancelled: function(touch) {
+ this._touch = NO;
+ this.get("layer").style.backgroundColor = "gray";
+ }
+
+ })
+
+});
+
+var MyExampleView = SC.View.extend({
+ backgroundColor: "#aaa",
+ childViews: "demo".w(),
+ demo: Tester.extend({
+ layout: { top: 10, left: 10, width: 200, height: 200 },
+ shouldStack: YES
+ })
+});
+
+// bootstrap code :)
+exports.getDemoView = function() {
+ return MyExampleView;
+};
View
43 docs/src/articles/touch/releasing.md
@@ -1,2 +1,43 @@
Releasing
-=========
+=========
+Why would you want to give up a touch? Imagine that your control is inside a `#js:SC.ScrollView`:
+if the touch moves too much, perhaps it should be considered a scroll, rather than an
+action for your control.
+
+From touchesDragged, you would give up touch responder status through a line like this:
+
+ #js
+ someTouch.makeTouchResponder(someTouch.nextTouchResponder);
+
+The touch's nextTouchResponder is the responder that is the _parent_ touch responder; through
+devious trickery (see *Capturing Touches*), ScrollView receives touch responder status _before_
+other views; further, it doesn't just hand touch responder status to the target view (your view)--
+it adds the responder to a stack of touch responders for the touch, so the responders can easily
+return to their parent responder (which is what you do with the above line of code.)
+
+Remember, though, that touchesDragged is called with a set of touches. It is really easy
+to change the responder for all of the touches simultaneously, should you wish to do so:
+
+ #js
+ touches.forEach(function(touch){
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ });
+
+Perhaps you want to pass control only if the responder is scrollable:
+
+ #js
+ if (touch.nextTouchResponder && touch.nextTouchResponder.isScrollable) {
+ touch.makeTouchResponder(touch.nextTouchResponder);
+ }
+
+`#js:touchCancelled` will be called on your view automatically.
+
+What Does It Look Like?
+-----------------------
+In this example, there is a single white box, containing a gray inner box. When you press
+on the inner box, the outer box will capture the touch first. After a delay, it re-captures
+by calling captureTouch, and the inner view receives it. This is just like the "Capturing" demo.
+
+However, the inner view, after a second, will release it back.
+
+{{demo:sc|releasing.js}}
2  frameworks/sproutcore
@@ -1 +1 @@
-Subproject commit b5ac726e0e347d7550d8aaacd4a424a2e10cfb33
+Subproject commit 89e1ef1f2c3c8823ad38d174d5250356d08a5901
Please sign in to comment.
Something went wrong with that request. Please try again.