ACTION-36: complete introduction; added usage examples and beginning of ReSpec syntax highlighter for code samples.
--- 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">
+ <!-- Declare which IndieUI event(s) this element receives. -->
+ <dialog <strong>ui-actions="dismiss"</strong> id="myDialog">
+ ...
+ </dialog>
+
+ <script type="text/javascript"></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">
+ </script>
+ </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">
+ <!-- Declare which IndieUI event(s) this element receives. -->
+ <canvas <strong>ui-actions="valuechange"</strong> id="slider" role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="42"></canvas>
+
+ <script type="text/javascript"></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">
+ </script>
+ </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">
+ <!-- body element is event listener for all events, but event receiver only for 'undo' actions. -->
<body <strong>ui-actions="undo"</strong>>
+
+ <!-- Element container for custom 'mapview' is the event receiver for 'pan' and 'zoom' actions. -->
<div id="mapview" <strong>ui-actions="pan zoom"</strong>> ... </div>
+
+ <!-- This Dialog is the event receiver for 'dismiss' actions initiated on any lower-level event target. -->
<dialog <strong>ui-actions="dismiss"</strong>> ... </dialog>
+
</body>
- <script type="text/javascript">
- // 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)
+ <script type="text/javascript"></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">
</script>
+ </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('<!--', '<span class="comment blockcomment"><!--')
+ lines[i] = lines[i].replace('-->', '--></span>')
+ }
+ return lines.join('\n'); // reassemble the string
+
+}
+