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 633c329b52e26b
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
     1.1 --- a/src/css/screen.css	Fri Dec 21 10:27:13 2012 -0800
     1.2 +++ b/src/css/screen.css	Fri Dec 21 15:01:15 2012 -0800
     1.3 @@ -97,3 +97,13 @@
     1.4  ol li {
     1.5  	margin-bottom:1em;
     1.6  }
     1.7 +
     1.8 +
     1.9 +/* Example syntax highlighting */
    1.10 +pre.example {
    1.11 +	color: #000;
    1.12 +}
    1.13 +pre.example .comment {
    1.14 +	color: #808080; /* 50% gray */
    1.15 +}
    1.16 +
     2.1 --- a/src/indie-ui-events.html	Fri Dec 21 10:27:13 2012 -0800
     2.2 +++ b/src/indie-ui-events.html	Fri Dec 21 15:01:15 2012 -0800
     2.3 @@ -120,7 +120,7 @@
     2.4  					<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>
     2.5  					<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>
     2.6  					<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>
     2.7 -				</ul>
     2.8 +				</ol>
     2.9  			</section>
    2.10  
    2.11  			<section id="intro-scope" class="informative">
    2.12 @@ -130,9 +130,84 @@
    2.13  				<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>
    2.14  			</section>
    2.15  
    2.16 -			<section id="intro-out-of-scope" class="informative">
    2.17 +			<section id="intro-usage">
    2.18  				<h3>Usage Examples</h3>
    2.19 -				<p class="placeholder">placeholder content</p>
    2.20 +				
    2.21 +				<section id="intro-example-dismissrequest"0>
    2.22 +					<h4>Dismissing a Modal Dialog</h4>
    2.23 +					<p>The following example uses a 'dismissrequest' event to close or cancel out of a modal application dialog.</p>
    2.24 +					<pre class="example">
    2.25 +						<span class="markup" data-transform="syntaxMarkup">
    2.26 +						&lt;!-- Declare which IndieUI event(s) this element receives. --&gt;
    2.27 +						&lt;dialog <strong>ui-actions="dismiss"</strong> id="myDialog"&gt;
    2.28 +						  ...
    2.29 +						&lt;/dialog&gt;
    2.30 +						
    2.31 +						&lt;script type="text/javascript"&gt;</span><!--
    2.32 +						--><span class="javascript" data-transform="syntaxJavaScript">
    2.33 +						  
    2.34 +						  var myDialog = document.getElementById('myDialog');
    2.35 +						  
    2.36 +						  // register the event at initialization
    2.37 +						  // <strong>Option #1:</strong> On the receiver itself... (See next example for Option #2)
    2.38 +						  <strong>myDialog.addEventListener('dismissrequest', dismissHandler);</strong>
    2.39 +						
    2.40 +						  // at some point during runtime, the handler will be called
    2.41 +						  // (e.g. if the user presses ESC key while focus is inside the dialog)
    2.42 +						  function dismissHandler(e) {
    2.43 +						  
    2.44 +						    // cancel and close the dialog (don't forget to move focus before closing)
    2.45 +						    closeDialog(<strong>e.receiver</strong>); // Event.receiver is a readonly property like Event.target 
    2.46 +						    
    2.47 +						    // then cancel the event
    2.48 +						    e.stopPropagation(); // stop the event from bubbling.
    2.49 +						    <strong>e.preventDefault();</strong> // let the UA/AT know the event was intercepted successfully.
    2.50 +
    2.51 +						  }</span>
    2.52 +						<span class="markup" data-transform="syntaxMarkup">
    2.53 +						&lt;/script&gt;
    2.54 +						</span>
    2.55 +					</pre>
    2.56 +				</section>
    2.57 +				
    2.58 +				<section id="intro-example-valuechangerequest"0>
    2.59 +					<h4>Changing the Value of a Custom Slider</h4>
    2.60 +					<p>The following example uses a 'valuechangerequest' event to modify the value of a custom ARIA slider.</p>
    2.61 +					<pre class="example">
    2.62 +						<span class="markup" data-transform="syntaxMarkup">
    2.63 +						&lt;!-- Declare which IndieUI event(s) this element receives. --&gt;
    2.64 +						&lt;canvas <strong>ui-actions="valuechange"</strong> id="slider" role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="42"&gt;&lt;/canvas&gt;
    2.65 +						
    2.66 +						&lt;script type="text/javascript"&gt;</span><!--
    2.67 +						--><span class="javascript" data-transform="syntaxJavaScript">
    2.68 +						  
    2.69 +						  // register the event at initialization
    2.70 +						  // <strong>Option #2:</strong> Using event delegation on any node (such as the body) that is higher in the DOM than the receiver element...
    2.71 +						  <strong>document.body.addEventListener('valuechangerequest', valueChangeHandler);</strong>
    2.72 +						
    2.73 +						  // at some point during runtime, the handler will be called
    2.74 +						  function valueChangeHandler(e) {
    2.75 +						    
    2.76 +						    // Find the event receiver element
    2.77 +						    var slider = e.receiver;
    2.78 +						    
    2.79 +						    // grab context info from the Event object
    2.80 +						    var changeType = <strong>e.request.changeType</strong>; // todo: Event.request object yet to be defined
    2.81 +						    
    2.82 +						    // update the model and display
    2.83 +						    myApp.requestValueChangeForElement(changeType, slider);
    2.84 +						
    2.85 +						    // cancel the event
    2.86 +						    e.stopPropagation(); // stop the event from bubbling 
    2.87 +						    <strong>e.preventDefault();</strong> // let the UA/AT know the event was intercepted successfully
    2.88 +						
    2.89 +						  }</span>
    2.90 +						<span class="markup" data-transform="syntaxMarkup">
    2.91 +						&lt;/script&gt;
    2.92 +						</span>
    2.93 +					</pre>
    2.94 +				</section>
    2.95 +				
    2.96  			</section>
    2.97  			
    2.98  			<section id="intro-backwards-compatibility" class="informative">
    2.99 @@ -156,6 +231,7 @@
   2.100  					<dt>attribute DOMString uiActions</dt>
   2.101  					<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>
   2.102  				</dl>
   2.103 +				<p class="ednote">It may be more appropriate to name this receives/@receives than uiActions/@ui-actions.</p>
   2.104  			</section>
   2.105  			
   2.106  			<section id="ui-actions">
   2.107 @@ -165,21 +241,31 @@
   2.108  				<div data-transform="listActions"><!-- dynamically generates event list --></div>
   2.109  				<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>
   2.110  				<pre class="example">
   2.111 +					<span class="markup" data-transform="syntaxMarkup">
   2.112 +					&lt;!-- body element is event listener for all events, but event receiver only for 'undo' actions. --&gt;
   2.113  					&lt;body <strong>ui-actions="undo"</strong>&gt;
   2.114 +					
   2.115 +					  &lt;!-- Element container for custom 'mapview' is the event receiver for 'pan' and 'zoom' actions. --&gt;
   2.116  					  &lt;div id="mapview" <strong>ui-actions="pan zoom"</strong>&gt; ... &lt;/div&gt;
   2.117 +					
   2.118 +					  &lt;!-- This Dialog is the event receiver for 'dismiss' actions initiated on any lower-level event target. --&gt;
   2.119  					  &lt;dialog <strong>ui-actions="dismiss"</strong>&gt; ... &lt;/dialog&gt;
   2.120 +					
   2.121  					&lt;/body&gt;
   2.122  					
   2.123 -					&lt;script type="text/javascript"&gt;
   2.124 -					  // registered on body as an example of event delegation to help illustrate the difference between
   2.125 -					  // event target (document.activeElement or other point-of-regard), receiver (element with defined actions), and listener (body)
   2.126 +					&lt;script type="text/javascript"&gt;</span>
   2.127 +					  <span class="javascript" data-transform="syntaxJavaScript">
   2.128 +					  // registered all of these on the body as an example of event delegation to help illustrate the difference between event
   2.129 +					  // target (document.activeElement or other point-of-regard), receiver (element with defined actions), and listener (body)
   2.130  					  document.body.addEventListener(<strong>'dismissrequest'</strong>, handleDismiss);
   2.131  					  document.body.addEventListener(<strong>'panrequest'</strong>, handlePan);
   2.132  					  document.body.addEventListener(<strong>'undorequest'</strong>, handleUndo);
   2.133  					  document.body.addEventListener(<strong>'zoomrequest'</strong>, handleZoom);
   2.134 +					</span><span class="markup" data-transform="syntaxMarkup">
   2.135  					&lt;/script&gt;
   2.136 +					</span>
   2.137  				</pre>
   2.138 -				<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>
   2.139 +				<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>
   2.140  			</section>
   2.141  
   2.142  		</section>
     3.1 --- a/src/js/respec-transformers.js	Fri Dec 21 10:27:13 2012 -0800
     3.2 +++ b/src/js/respec-transformers.js	Fri Dec 21 15:01:15 2012 -0800
     3.3 @@ -1,8 +1,9 @@
     3.4  
     3.5 +// utility used by both listEvents and listActions
     3.6  function events() {
     3.7  	var eventList = [], nodeList = $$('code.event');
     3.8 -	for (index in nodeList) {
     3.9 -		var title = nodeList[index].innerText;
    3.10 +	for (var i=0; i<nodeList.length; i++) {
    3.11 +		var title = nodeList[i].innerText;
    3.12  		if ($$('#'+title).length) eventList.push(title);
    3.13  	}
    3.14  	return eventList.sort();
    3.15 @@ -11,8 +12,8 @@
    3.16  /* listEvents: alphabetical list of event listeners, generated from markup e.g. 'collapserequest, deleterequest, ...' */
    3.17  function listEvents(r, content) {
    3.18  	var s = '<ul>', eventList = events();
    3.19 -	for (index in eventList){
    3.20 -		var title = eventList[index];
    3.21 +	for (var i=0; i<eventList.length; i++){
    3.22 +		var title = eventList[i];
    3.23  		var description = '';
    3.24  		var els = $$('#'+title+'+dd>p'); // get the paragraph children of the dd that follows the dt event element.
    3.25  		if (els.length) description = els[0].innerText; // use its text value as the short description
    3.26 @@ -25,11 +26,51 @@
    3.27  /* listActions: alphabetical list generated from trimmed event names. e.g. 'collapserequest, deleterequest, ...' becomes 'collapse, delete, ...' */
    3.28  function listActions(r, content) {
    3.29  	var s = '<ul>', eventList = events();
    3.30 -	for (index in eventList){
    3.31 -		var title = eventList[index];
    3.32 +	for (var i=0; i<eventList.length; i++){
    3.33 +		var title = eventList[i];
    3.34  		s += '<li><code>' +title.replace('request','')+ '</code></li>';
    3.35  	}
    3.36  	s += '</ul>'
    3.37  	return content + s;
    3.38  }
    3.39  
    3.40 +
    3.41 +
    3.42 +/* syntax highlighting for JavaScript examples */
    3.43 +function syntaxJavaScript(r, content) {
    3.44 +	lines = content.split(/\n/);
    3.45 +	for (var i=0; i<lines.length; i++) {
    3.46 +		// line comments
    3.47 +		if (lines[i].indexOf('//') !== -1) {
    3.48 +			lines[i] = lines[i].replace('//', '<span class="comment linecomment">//').replace(/$/, '</span>');
    3.49 +		}
    3.50 +		// block comments
    3.51 +		lines[i] = lines[i].replace('/*', '<span class="comment blockcomment">/*')
    3.52 +		lines[i] = lines[i].replace('*/', '*/</span>')
    3.53 +	}
    3.54 +	return lines.join('\n'); // reassemble the string
    3.55 +}
    3.56 +
    3.57 +/* syntax highlighting for CSS examples */
    3.58 +function syntaxCSS(r, content) {
    3.59 +	lines = content.split(/\n/);
    3.60 +	for (var i=0; i<lines.length; i++) {
    3.61 +		// block comments
    3.62 +		lines[i] = lines[i].replace('/*', '<span class="comment blockcomment">/*')
    3.63 +		lines[i] = lines[i].replace('*/', '*/</span>')
    3.64 +	}
    3.65 +	return lines.join('\n'); // reassemble the string
    3.66 +}
    3.67 +
    3.68 +/* syntax highlighting for markup examples */
    3.69 +function syntaxMarkup(r, content) {
    3.70 +	lines = content.split(/\n/);
    3.71 +	for (var i=0; i<lines.length; i++) {
    3.72 +		// comments
    3.73 +		lines[i] = lines[i].replace('&lt;!--', '<span class="comment blockcomment">&lt;!--')
    3.74 +		lines[i] = lines[i].replace('--&gt;', '--&gt;</span>')
    3.75 +	}
    3.76 +	return lines.join('\n'); // reassemble the string
    3.77 +	
    3.78 +}
    3.79 +