ACTION-36: complete introduction; added usage examples and beginning of ReSpec syntax highlighter for code samples.
authorJames Craig <jcraig@apple.com>
Fri, 21 Dec 2012 15:01:15 -0800
changeset 63 3c329b52e26b
parent 62 74abaa488438
child 64 03ebe5cd588c
ACTION-36: complete introduction; added usage examples and beginning of ReSpec syntax highlighter for code samples.
src/css/screen.css
src/indie-ui-events.html
src/js/respec-transformers.js
--- a/src/css/screen.css	Fri Dec 21 10:27:13 2012 -0800
+++ b/src/css/screen.css	Fri Dec 21 15:01:15 2012 -0800
@@ -97,3 +97,13 @@
 ol li {
 	margin-bottom:1em;
 }
+
+
+/* Example syntax highlighting */
+pre.example {
+	color: #000;
+}
+pre.example .comment {
+	color: #808080; /* 50% gray */
+}
+
--- a/src/indie-ui-events.html	Fri Dec 21 10:27:13 2012 -0800
+++ b/src/indie-ui-events.html	Fri Dec 21 15:01:15 2012 -0800
@@ -120,7 +120,7 @@
 					<li>Make it easier for web developers to author consistently usable interfaces that are agnostic and independent of a user's particular platform, hardware, locale, and preferences.</li>
 					<li>Enable every type of control in these interfaces to be programmatically determinable and controllable by both mainstream and alternate forms of user input, including assistive technologies.</li>
 					<li>Provide a clear path for web developers to smoothly transition from currently existing physical events to IndieUI events, during the period when implementations of IndieUI are incomplete.</li>
-				</ul>
+				</ol>
 			</section>
 
 			<section id="intro-scope" class="informative">
@@ -130,9 +130,84 @@
 				<p>For example, it may be common for the <kbd>ESC</kbd> key to trigger a 'dismissrequest' event to close a dialog, but the decision to do so by physically pressing the <kbd>ESC</kbd> key is left as an implementation detail. It is up to each platform to determine whether <kbd>ESC</kbd> or some other interaction triggers the 'dismissrequest' event. As long as there is some way to initiate an event, the user agent will be considered a conforming implementation.</p>
 			</section>
 
-			<section id="intro-out-of-scope" class="informative">
+			<section id="intro-usage">
 				<h3>Usage Examples</h3>
-				<p class="placeholder">placeholder content</p>
+				
+				<section id="intro-example-dismissrequest"0>
+					<h4>Dismissing a Modal Dialog</h4>
+					<p>The following example uses a 'dismissrequest' event to close or cancel out of a modal application dialog.</p>
+					<pre class="example">
+						<span class="markup" data-transform="syntaxMarkup">
+						&lt;!-- Declare which IndieUI event(s) this element receives. --&gt;
+						&lt;dialog <strong>ui-actions="dismiss"</strong> id="myDialog"&gt;
+						  ...
+						&lt;/dialog&gt;
+						
+						&lt;script type="text/javascript"&gt;</span><!--
+						--><span class="javascript" data-transform="syntaxJavaScript">
+						  
+						  var myDialog = document.getElementById('myDialog');
+						  
+						  // register the event at initialization
+						  // <strong>Option #1:</strong> On the receiver itself... (See next example for Option #2)
+						  <strong>myDialog.addEventListener('dismissrequest', dismissHandler);</strong>
+						
+						  // at some point during runtime, the handler will be called
+						  // (e.g. if the user presses ESC key while focus is inside the dialog)
+						  function dismissHandler(e) {
+						  
+						    // cancel and close the dialog (don't forget to move focus before closing)
+						    closeDialog(<strong>e.receiver</strong>); // Event.receiver is a readonly property like Event.target 
+						    
+						    // then cancel the event
+						    e.stopPropagation(); // stop the event from bubbling.
+						    <strong>e.preventDefault();</strong> // let the UA/AT know the event was intercepted successfully.
+
+						  }</span>
+						<span class="markup" data-transform="syntaxMarkup">
+						&lt;/script&gt;
+						</span>
+					</pre>
+				</section>
+				
+				<section id="intro-example-valuechangerequest"0>
+					<h4>Changing the Value of a Custom Slider</h4>
+					<p>The following example uses a 'valuechangerequest' event to modify the value of a custom ARIA slider.</p>
+					<pre class="example">
+						<span class="markup" data-transform="syntaxMarkup">
+						&lt;!-- Declare which IndieUI event(s) this element receives. --&gt;
+						&lt;canvas <strong>ui-actions="valuechange"</strong> id="slider" role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="42"&gt;&lt;/canvas&gt;
+						
+						&lt;script type="text/javascript"&gt;</span><!--
+						--><span class="javascript" data-transform="syntaxJavaScript">
+						  
+						  // register the event at initialization
+						  // <strong>Option #2:</strong> Using event delegation on any node (such as the body) that is higher in the DOM than the receiver element...
+						  <strong>document.body.addEventListener('valuechangerequest', valueChangeHandler);</strong>
+						
+						  // at some point during runtime, the handler will be called
+						  function valueChangeHandler(e) {
+						    
+						    // Find the event receiver element
+						    var slider = e.receiver;
+						    
+						    // grab context info from the Event object
+						    var changeType = <strong>e.request.changeType</strong>; // todo: Event.request object yet to be defined
+						    
+						    // update the model and display
+						    myApp.requestValueChangeForElement(changeType, slider);
+						
+						    // cancel the event
+						    e.stopPropagation(); // stop the event from bubbling 
+						    <strong>e.preventDefault();</strong> // let the UA/AT know the event was intercepted successfully
+						
+						  }</span>
+						<span class="markup" data-transform="syntaxMarkup">
+						&lt;/script&gt;
+						</span>
+					</pre>
+				</section>
+				
 			</section>
 			
 			<section id="intro-backwards-compatibility" class="informative">
@@ -156,6 +231,7 @@
 					<dt>attribute DOMString uiActions</dt>
 					<dd>A attribute whose string value <a href="#def_reflected_attribute">reflects</a> the value of the <a href="#ui-actions"><code>ui-actions</code></a> content attribute.</dd>
 				</dl>
+				<p class="ednote">It may be more appropriate to name this receives/@receives than uiActions/@ui-actions.</p>
 			</section>
 			
 			<section id="ui-actions">
@@ -165,21 +241,31 @@
 				<div data-transform="listActions"><!-- dynamically generates event list --></div>
 				<p class="ednote">We could probably combine the 'manipulation' events into a single 'manipulation' action value. I don't foresee a case where an author would want to receive some, but not all of them, and even if that case exists, the author could just not listen for those specific events.</p>
 				<pre class="example">
+					<span class="markup" data-transform="syntaxMarkup">
+					&lt;!-- body element is event listener for all events, but event receiver only for 'undo' actions. --&gt;
 					&lt;body <strong>ui-actions="undo"</strong>&gt;
+					
+					  &lt;!-- Element container for custom 'mapview' is the event receiver for 'pan' and 'zoom' actions. --&gt;
 					  &lt;div id="mapview" <strong>ui-actions="pan zoom"</strong>&gt; ... &lt;/div&gt;
+					
+					  &lt;!-- This Dialog is the event receiver for 'dismiss' actions initiated on any lower-level event target. --&gt;
 					  &lt;dialog <strong>ui-actions="dismiss"</strong>&gt; ... &lt;/dialog&gt;
+					
 					&lt;/body&gt;
 					
-					&lt;script type="text/javascript"&gt;
-					  // registered on body as an example of event delegation to help illustrate the difference between
-					  // event target (document.activeElement or other point-of-regard), receiver (element with defined actions), and listener (body)
+					&lt;script type="text/javascript"&gt;</span>
+					  <span class="javascript" data-transform="syntaxJavaScript">
+					  // registered all of these on the body as an example of event delegation to help illustrate the difference between event
+					  // target (document.activeElement or other point-of-regard), receiver (element with defined actions), and listener (body)
 					  document.body.addEventListener(<strong>'dismissrequest'</strong>, handleDismiss);
 					  document.body.addEventListener(<strong>'panrequest'</strong>, handlePan);
 					  document.body.addEventListener(<strong>'undorequest'</strong>, handleUndo);
 					  document.body.addEventListener(<strong>'zoomrequest'</strong>, handleZoom);
+					</span><span class="markup" data-transform="syntaxMarkup">
 					&lt;/script&gt;
+					</span>
 				</pre>
-				<p class="note">In the previous example, 'undorequest' and 'redorequest' events could be fired any time the user's point-of-regard was inside the document. However, the 'dismissrequest' would only be fired when the user's point-of-regard was inside the dialog. Likewise, the 'panrequest' and 'zoomrequest' would only be fired when the user's <a href="#def_point_of_regard">point-of-regard</a> was inside the map view.</p>
+				<p class="note">In the previous example, the 'undorequest' event may be fired any time the user's point-of-regard was inside the document<!-- , presumably when the user triggered their platform's physical event to undo an action, such as <kbd>Control+Z</kbd> or <kbd>Command+Z</kbd> -->. However, the 'dismissrequest' would only be fired when the user's point-of-regard was inside the dialog. Likewise, the 'panrequest' and 'zoomrequest' would only be fired when the user's <a href="#def_point_of_regard">point-of-regard</a> was inside the map view.</p>
 			</section>
 
 		</section>
--- a/src/js/respec-transformers.js	Fri Dec 21 10:27:13 2012 -0800
+++ b/src/js/respec-transformers.js	Fri Dec 21 15:01:15 2012 -0800
@@ -1,8 +1,9 @@
 
+// utility used by both listEvents and listActions
 function events() {
 	var eventList = [], nodeList = $$('code.event');
-	for (index in nodeList) {
-		var title = nodeList[index].innerText;
+	for (var i=0; i<nodeList.length; i++) {
+		var title = nodeList[i].innerText;
 		if ($$('#'+title).length) eventList.push(title);
 	}
 	return eventList.sort();
@@ -11,8 +12,8 @@
 /* listEvents: alphabetical list of event listeners, generated from markup e.g. 'collapserequest, deleterequest, ...' */
 function listEvents(r, content) {
 	var s = '<ul>', eventList = events();
-	for (index in eventList){
-		var title = eventList[index];
+	for (var i=0; i<eventList.length; i++){
+		var title = eventList[i];
 		var description = '';
 		var els = $$('#'+title+'+dd>p'); // get the paragraph children of the dd that follows the dt event element.
 		if (els.length) description = els[0].innerText; // use its text value as the short description
@@ -25,11 +26,51 @@
 /* listActions: alphabetical list generated from trimmed event names. e.g. 'collapserequest, deleterequest, ...' becomes 'collapse, delete, ...' */
 function listActions(r, content) {
 	var s = '<ul>', eventList = events();
-	for (index in eventList){
-		var title = eventList[index];
+	for (var i=0; i<eventList.length; i++){
+		var title = eventList[i];
 		s += '<li><code>' +title.replace('request','')+ '</code></li>';
 	}
 	s += '</ul>'
 	return content + s;
 }
 
+
+
+/* syntax highlighting for JavaScript examples */
+function syntaxJavaScript(r, content) {
+	lines = content.split(/\n/);
+	for (var i=0; i<lines.length; i++) {
+		// line comments
+		if (lines[i].indexOf('//') !== -1) {
+			lines[i] = lines[i].replace('//', '<span class="comment linecomment">//').replace(/$/, '</span>');
+		}
+		// block comments
+		lines[i] = lines[i].replace('/*', '<span class="comment blockcomment">/*')
+		lines[i] = lines[i].replace('*/', '*/</span>')
+	}
+	return lines.join('\n'); // reassemble the string
+}
+
+/* syntax highlighting for CSS examples */
+function syntaxCSS(r, content) {
+	lines = content.split(/\n/);
+	for (var i=0; i<lines.length; i++) {
+		// block comments
+		lines[i] = lines[i].replace('/*', '<span class="comment blockcomment">/*')
+		lines[i] = lines[i].replace('*/', '*/</span>')
+	}
+	return lines.join('\n'); // reassemble the string
+}
+
+/* syntax highlighting for markup examples */
+function syntaxMarkup(r, content) {
+	lines = content.split(/\n/);
+	for (var i=0; i<lines.length; i++) {
+		// comments
+		lines[i] = lines[i].replace('&lt;!--', '<span class="comment blockcomment">&lt;!--')
+		lines[i] = lines[i].replace('--&gt;', '--&gt;</span>')
+	}
+	return lines.join('\n'); // reassemble the string
+	
+}
+