first round of media features
authorJames Craig <jcraig@apple.com>
Thu, 07 Nov 2013 00:25:00 -0800
changeset 146 6daaebf83e43
parent 145 172c675f7a80
child 147 b77541fae774
first round of media features
src/css/screen.css
src/indie-ui-context.html
src/indie-ui-events.html
src/js/respec-transformers.js
--- a/src/css/screen.css	Wed Nov 06 17:32:44 2013 -0800
+++ b/src/css/screen.css	Thu Nov 07 00:25:00 2013 -0800
@@ -8,22 +8,22 @@
 }
 
 .ednote {
-	color:#c00 !important;
-	font-style:italic;
-	position:relative;
+	color: #c00 !important;
+	font-style: italic;
+	position: relative;
 }
 div.ednote, p.ednote{
-	padding-right:150px;
+	padding-right: 150px;
 }
 div.ednote:before, p.ednote:before{
-	content: 'Editorial Note';
-	position:absolute;
-	top:0;
-	right:0;
-	font-size:11px;
-	padding:0.2em 0.5em;
-	margin:0;
-	border:solid 1px #c00;
+	content: 'Editorial Note'; /* todo: localize as attr(data-label) */
+	position: absolute;
+	top: 0;
+	right: 0;
+	font-size: 11px;
+	padding: 0.2em 0.5em;
+	margin: 0;
+	border: solid 1px #c00;
 }
 
 [hidden] {
@@ -31,43 +31,47 @@
 }
 
 .todo, .todo:before {
-	color:#c00 !important;
-	border-color:#c00 !important;
+	color: #c00 !important;
+	border-color: #c00 !important;
 }
 .todo[title]:before{
-	content: 'To-do';
-	position:absolute;
-	top:0;
-	right:0;
-	font-size:11px;
-	padding:0.2em 0.5em;
-	margin:0;
+	content: 'To-do'; /* todo: localize as attr(data-label) */
+	position: absolute;
+	top: 0;
+	right: 0;
+	font-size: 11px;
+	padding: 0.2em 0.5em;
+	margin: 0;
 	border:solid 1px #c00;
 	border-width: 0 0 1px 1px;
 }
 
-.example {
+/* .ex class for example containers b/c .example is reserved by ReSpec */
+.ex {
 	margin: 1em 0;
 	padding: 0.7em 1em 0.2em;
 	border: solid 1px #999;
-	position:relative;
+	position: relative;
+	color: inherit;
+	background-color: inherit;
+	display: block;
 }
-.example[title]:before{
-	content:attr(title);
-	position:absolute;
-	top:0;
-	left:0;
-	font-size:11px;
-	padding:0.2em 0.5em;
-	margin:0;
-	border:solid 1px #999;
+.ex[title]:before{
+	content: attr(title);
+	position: absolute;
+	top: 0;
+	left: 0;
+	font-size: 11px;
+	padding: 0.2em 0.5em;
+	margin: 0;
+	border: solid 1px #999;
 	border-width: 0 1px 1px 0;
 }
-.example h4, .note h4{
-	margin:0.5em 0;
+.ex h4, .note h4{
+	margin: 0.5em 0;
 }
-.example ol li, .note ol li{
-	margin:0 0 0.5em;
+.ex ol li, .note ol li{
+	margin: 0 0 0.5em;
 }
 
 html code, html pre, html kbd{ /* more specific selector than the default W3C style sheet */
@@ -111,3 +115,16 @@
 	color: #808080; /* 50% gray */
 }
 
+dl.properties dt {
+	float: left;
+	margin-right: 0.5em;
+	font-weight: normal;
+	font-style: italic;
+}
+dl.properties dt::after {
+	content: ":";
+}
+
+.relatedconcepts li {
+	margin-bottom: 0.6em;
+}
--- a/src/indie-ui-context.html	Wed Nov 06 17:32:44 2013 -0800
+++ b/src/indie-ui-context.html	Thu Nov 07 00:25:00 2013 -0800
@@ -109,7 +109,242 @@
 		</section>
 		<!-- :::::::::::::::::::: END INTRO :::::::::::::::::::: -->
 		
-		
+		<!-- :::::::::::::::::::: Media Features :::::::::::::::::::: -->
+		<section id="MediaFeatures">
+			<h2>Media Features</h2>
+			<p>This section defines media features using syntax defined in the CSS3 Media Queries specification, but adds a RestrictionCategory parameter used by the access control extension to the MediaQueryList interface and the @media selector. <span class="todo">Todo: link these the the relevant portions of the access control extension.</span></p>
+			<p>The media features are grouped by restriction categories (e.g. type settings, media settings, etc.) that define related media features, and recommended default restriction levels.</p>
+
+			<section id="ColorSettings" class="restrictioncategory">
+				<h3><code>ColorSettings</code></h3>
+
+				<dl class="properties">
+					
+					<dt>Default restriction</dt>
+					<dd>none</dd>
+					
+					<dt>Allowed from</dt>
+					<dd>domain (e.g. not advertisers and third-party sites)</dd>
+
+				</dl>
+
+				<p class="note">Color settings are not be restricted by default from the requesting page, primarily because a site can figure out most of this information using some creative CSS and JavaScript. These keys are therefore primarily intended as convenience accessors so that web authors can more easily provide adaptive interfaces that work well for all users. The display inversion feature is not currently detectable, but does not represent a major concern for privacy or fingerprinting.</p>
+				<p class="ednote">Note: An equivalent to Microsoft's high-contrast settings may end up in a restricted category if it's determined they open the user to privacy or fingerprinting implications.</p>
+
+				<section id="user-color">
+					<h4 class="media-feature"><code>user-color</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>&lt;color&gt;</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>No</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">ColorSettings</dd>
+						
+					</dl>
+					<p class="ednote">Need to determine how to match color hue or value ranges (potentially via HSL) so that we could expose min/max on colors. Otherwise, this may not be usable.</p>
+				</section>
+
+				<section id="user-background-color">
+					<h4 class="media-feature"><code>user-background-color</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>&lt;color&gt;</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>No</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">ColorSettings</dd>
+						
+					</dl>
+					<p class="ednote">Need to determine how to match color hue or value ranges (potentially via HSL) so that we could expose min/max on colors. Otherwise, this may not be usable.</p>
+				</section>
+
+				<section id="display-colors-inverted">
+					<h4 class="media-feature"><code>display-colors-inverted</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>inverted | off</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>No</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">ColorSettings</dd>
+						
+					</dl>
+
+					<div class="ex" title="Informative">
+						<p>In this example, the hardware display rendering is inverted, so the web app could <em>double-invert</em> foreground image and video content, which usually looks strange while inverted. This would leave text foreground color, all background colors, and background styles inverted to adhere to user setting.</p>
+						<pre class="example css" data-transform="syntaxCSS">
+							@media (display-colors-inverted: inverted) {
+							    img, video {
+							        filter: invert(100%);
+							    }
+							}
+						</pre> 
+						<figure>
+							<img src="./img/uc-inverted.png" alt="Screen shot of Twitter mobile web site displayed on iOS with screen colors inverted." height="320" width="181">
+							<img src="./img/uc-double-inverted.png" alt="Mock up of previous screen shot with user profile images double-inverted, to achieve a more natural rendering and skin color." height="320" width="181">
+							<figcaption>Everything in the first screen shot, including the user profile image, is inverted so skin tones are unnatural. A web application could choose to double-invert content images, as is done in the second screen shot.</figcaption>
+						</figure>
+					</div>
+
+					<p class="note">Note: Privacy and fingerprinting concerns related to this media feature are minimal, since it is unlikely that most individuals will have this setting enabled all the time. For example, due to personal preference or situational context, some individuals use this as a manual quick toggle to temporarily view text content in a light-on-dark color scheme as opposed to a dark-on-light default.</p>
+
+					<section class="relatedconcepts">
+						<h5>Concepts related to display-colors-inverted</h5>
+						<ul>
+							<li>
+								Apple UIKit API for detecting color inversion on iOS<br>
+								<code class="ex">
+									// From &lt;UIKit/UIAccessibility.h&gt;<br>
+									// Returns whether the system preference for invert colors is enabled.<br>
+									UIKIT_EXTERN BOOL <a href="https://developer.apple.com/library/ios/documentation/uikit/reference/UIKitFunctionReference/Reference/reference.html#//apple_ref/c/func/UIAccessibilityIsInvertColorsEnabled">UIAccessibilityIsInvertColorsEnabled()</a> NS_AVAILABLE_IOS(6_0);<br>
+									UIKIT_EXTERN NSString *const <a href="https://developer.apple.com/library/ios/documentation/uikit/reference/UIAccessibility_Protocol/Introduction/Introduction.html#//apple_ref/c/data/UIAccessibilityInvertColorsStatusDidChangeNotification">UIAccessibilityInvertColorsStatusDidChangeNotification</a> NS_AVAILABLE_IOS(6_0);<br>
+								</code>
+							</li>
+
+							<li>Mac OS X and other platforms have similar features to invert display colors.</li>
+							
+						</ul>
+					</section>
+
+				</section>
+
+			</section>
+
+			<section id="TypeSettings" class="restrictioncategory">
+				<h3><code>TypeSettings</code></h3>
+
+				<dl class="properties">
+					
+					<dt>Default restriction</dt>
+					<dd>none</dd>
+					
+					<dt>Allowed from</dt>
+					<dd>domain (e.g. not advertisers and third-party sites)</dd>
+
+				</dl>
+
+				<p class="note">Type settings are not restricted by default from the requesting page, because a site can figure out all of this information by creatively using CSS and JavaScript. These keys are therefore primarily intended as convenience accessors so that web authors can more easily provide adaptive interfaces that work well for all users.</p>
+
+				<section id="user-font-size">
+					<h4 class="media-feature"><code>user-font-size</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>&lt;Number&gt; (All values converted to finite CSS pixels)</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>Yes</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">TypeSettings</dd>
+						
+					</dl>
+
+					<pre class="example css" data-transform="syntaxCSS">
+						/* Default layout uses 2 columns */
+						main {
+						    columns: 2;
+						}
+
+						/* But if the user's default font size (from browser text zoom setting or... */
+						/* user style sheet...) is larger than 32px, drop the columns. */
+						/* Note: syntax might be more understandable as (user-font-size > 32px) */
+						@media (min-user-font-size: 32px) { 
+						    main {
+						        columns: auto;
+						    }
+						}
+					</pre> 
+
+				</section>
+
+				<section id="user-line-height">
+					<h4 class="media-feature"><code>user-line-height</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>&lt;Number&gt; (All values converted to finite CSS pixels)</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>Yes</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">TypeSettings</dd>
+						
+					</dl>
+					<p class="note">The working group does not expect this media feature to be used frequently, but line-height, letter-spacing, and word-spacing preferences can be important for users with cognitive impairments such as dyslexia and <abbr title="Autism Spectrum Disorder">ASD</abbr>, so it's important to respect a user's default settings.</p>
+				</section>
+
+				<section id="user-letter-spacing">
+					<h4 class="media-feature"><code>user-letter-spacing</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>&lt;Number&gt; (All values converted to finite CSS pixels)</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>Yes</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">TypeSettings</dd>
+						
+					</dl>
+					<p class="note">The working group does not expect this media feature to be used frequently, but line-height, letter-spacing, and word-spacing preferences can be important for users with cognitive impairments such as dyslexia and <abbr title="Autism Spectrum Disorder">ASD</abbr>, so it's important to respect a user's default settings.</p>
+				</section>
+
+				<section id="user-word-spacing">
+					<h4 class="media-feature"><code>user-word-spacing</code></h4>
+					<dl class="properties">
+						
+						<dt>Value</dt>
+						<dd>&lt;Number&gt; (All values converted to finite CSS pixels)</dd>
+						
+						<dt>Applies to</dt>
+						<dd>visual media</dd>
+						
+						<dt>Accepts min/max prefixes</dt>
+						<dd>Yes</dd>
+						
+						<dt>Restriction Category</dt>
+						<dd data-transform="linkId">TypeSettings</dd>
+						
+					</dl>
+					<p class="note">The working group does not expect this media feature to be used frequently, but line-height, letter-spacing, and word-spacing preferences can be important for users with cognitive impairments such as dyslexia and <abbr title="Autism Spectrum Disorder">ASD</abbr>, so it's important to respect a user's default settings.</p>
+				</section>
+
+			</section>
+
+		</section>
+		<!-- :::::::::::::::::::: END Media Features :::::::::::::::::::: -->
+
 		<!--
 		ReSpec example: Use @data-transform to reuse a content transformer, and @data-oninclude to transform external content prior to inclusion.
 		<script type="text/javascript">function xmp(r, content) { return content.replace(/</g,'&lt;').replace(/>/g,'&gt;'); } </script>
@@ -120,6 +355,7 @@
 			<div data-transform="listMediaFeatures"><!-- dynamically generates media feature list --></div>
 		</section>
 		<section id="terms" class="appendix" data-include="./include/terms.html"></section>
+		<p class="ednote">Glossary currently includes all terms in Events Module and User Context Module. Need to remove the ones that are not used in the current document.</p>
 		<section id="acknowledgements" class="appendix" data-include="./include/ack.html"></section>
 		
 	</body>
--- a/src/indie-ui-events.html	Wed Nov 06 17:32:44 2013 -0800
+++ b/src/indie-ui-events.html	Thu Nov 07 00:25:00 2013 -0800
@@ -345,7 +345,7 @@
 								<li>Bubbles: Yes</li>
 								<li>Cancelable: Yes</li>
 							</ul>
-							<div class="example" title="Informative Example">
+							<div class="ex" title="Informative Example">
 								<p>Users, wanting to 'undo' a discrete action in a web application, can indicate their intent a number of ways, including pressing <kbd>Control+Z</kbd> on Windows or Linux, <kbd>Command+Z</kbd> on Mac OS X, and even by shaking some accelerometer- or gyroscope-enabled mobile devices.</p>
 							</div>
 						</dd>
@@ -357,7 +357,7 @@
 								<li>Bubbles: Yes</li>
 								<li>Cancelable: Yes</li>
 							</ul>
-							<div class="example" title="Informative Example">
+							<div class="ex" title="Informative Example">
 								<p>Users, wanting to 'redo' a discrete action in a web application, can indicate their intent a number of ways, including pressing <kbd>Control+Shift+Z</kbd> on Windows or Linux, <kbd>Command+Shift+Z</kbd> on Mac OS X.</p>
 							</div>
 						</dd>
@@ -384,7 +384,7 @@
 								<li>Bubbles: Yes</li>
 								<li>Cancelable: Yes</li>
 							</ul>
-							<div class="example" title="Informative Example">
+							<div class="ex" title="Informative Example">
 								<p>Users, wanting to 'escape from' or 'dismiss' a web application state (for example, closing a modal dialog), can indicate their intent a number of ways, most commonly by pressing <kbd>Escape</kbd> on keyboard-controlled operating systems. Web authors who have registered for this event should process the event to determine whether to cancel the event. If the 'dismiss' action is understood in the context of the web application, web authors should perform the appropriate action (such as closing the dialog), and cancel the event using the event object's <code>preventDefault()</code> method.</p>
 							</div>
 						</dd>
@@ -789,7 +789,7 @@
 								<li>Cancelable: Yes</li>
 								<li>Context Info: <code>changeType</code></li>
 							</ul>
-							<div class="example" title="Informative Example">
+							<div class="ex" title="Informative Example">
 								<p>Users, wanting to change the value of a custom range widget (e.g. sliders or carousels) in a web application, can indicate their intent a number of ways, including pressing various keys (<kbd>Up</kbd>, <kbd>Down</kbd>, <kbd>Left</kbd>, <kbd>Right</kbd>, <kbd>PageUp</kbd>, <kbd>PageDown</kbd>, <kbd>Home</kbd>, <kbd>End</kbd>) on most keyboard-controlled interfaces. User agents understanding this intent should initiate a <code>valuechangerequest</code> event. Web authors who have registered for this event, should process the event to determine whether to cancel the event. If the value change action is understood in the context of the web application, web authors should change the value of the associated widget by an amount determined via the <code>changeType</code> argument, and cancel the event using the event object's <code>preventDefault()</code> method.</p>
 							</div>
 						</dd>
--- a/src/js/respec-transformers.js	Wed Nov 06 17:32:44 2013 -0800
+++ b/src/js/respec-transformers.js	Thu Nov 07 00:25:00 2013 -0800
@@ -37,9 +37,10 @@
 
 // utility used by listMediaFeatures
 function allMediaFeatures() {
-	var selector = '', mediaFeatureList = [], nodeList = $$('.mediafeature');
+	var node, selector = '', mediaFeatureList = [], nodeList = $$('.media-feature');
 	for (var i=0; i < nodeList.length; i++) {
-		mediaFeatureList.push(nodeList[i].id);
+		node = nodeList[i].parentElement.id;
+		mediaFeatureList.push(node);
 	}
 	return mediaFeatureList.sort();
 }
@@ -49,16 +50,17 @@
 	var s = '<ul>', mediaFeatureName = '', linkId = '', mediaFeatureList = allMediaFeatures();
 	for (var i = 0; i < mediaFeatureList.length; i++){
 		mediaFeatureName = mediaFeatureList[i];
-		// FIXME: this regex probably needs updating now that media features can contain hyphens
-		linkId = mediaFeatureName.replace(/([a-z]+)-([a-z]+)/i, 'widl-$2-$1'); // regex: hardcoded ID 'fooBar-bazBop' becomes ReSpec-generated ID 'widl-bazBop-fooBar'
-		mediaFeatureName = mediaFeatureName.substring(0, mediaFeatureName.indexOf('-'));
-		//console.log(mediaFeatureList[i] + ' : ' + mediaFeatureName + ' : ' + linkId);
+		linkId = mediaFeatureName;
 		s += '<li><code><a href="#' + linkId + '">' + mediaFeatureName + '</a></code></li>';
 	}
 	s += '</ul>';
 	return content + s;
 }
 
+/* Turns <el>myId</el> into <el><a href="myId">myId</a></el> */ 
+function linkId(r, content) {
+	return ['<a href="#', r.xmlEscape(content), '">', content, '</a>'].join('');	
+}
 
 /* syntax highlighting for JavaScript examples */
 function syntaxJavaScript(r, content) {