<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
	<channel>
		<title>dfkaye.com</title>
		<atom:link href="https://dfkaye.comdemos/" rel="self" type="application/rss+xml" />
		<link>https://dfkaye.com</link>
		<description>Thoughts on building &amp;amp; Testing JavaScript, CSS, HTML, et al…</description>
		<lastBuildDate>Fri, 06 Aug 2021 09:36:29 -0700
		</lastBuildDate>
		<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<generator>Hugo -- gohugo.io</generator>
		
    
		
		<item>
			<title>Demo: Alert-Dialog Polyfill</title>
			<link>https://dfkaye.com/demos/alert-dialog-generator/</link>
			<pubDate>Fri, 06 Aug 2021 09:36:29 -0700</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/alert-dialog-generator/</guid>
			
			<description><![CDATA[ Demo of a vanilla JavaScript polyfill for the browser's modal dialog methods alert(), confirm(), and prompt(), in case Google really removes them and breaks the web.]]></description>
			<content:encoded><![CDATA[ <h2 id="summary">Summary</h2>
<p>The modal dialog polyfill uses <code>async/await</code> syntax and a <code>generator</code> function to return responses to awaited <code>Promises</code>. For more detail, <a href="/posts/2021/08/10/alert-dialog-generator/">consult this post</a></p>
<h2 id="results">Results</h2>
<ul>
<li>Reasonably accessible on screen readers, but I&rsquo;ve tested only with Windows Navigator and Jaws so far.</li>
<li>Tested on Chrome, Edge, Firefox, and Falkon on a Windows 10 laptop.</li>
<li>Tested on iOS Safari (iPhone 7-plus; however, top-level <code>await</code> is not supported), as of 

<time datetime="2021-08-10">10 August 2021</time>
.</li>
</ul>
<h2 id="accessibility">Accessibility</h2>
<p>To close a custom modal dialog, you can either press the 

<kbd>Escape</kbd>
 key, or press 

<kbd>Tab</kbd>
 to the <code>OK</code> button and press the button or the 

<kbd>Enter</kbd>
 key.</p>
<h2 id="code-samples">Code samples</h2>
<ol>
<li>Use it in an event listener:</li>
</ol>
<div class="highlight"><pre style=";-moz-tab-size:2;-o-tab-size:2;tab-size:2"><code class="language-js" data-lang="js"><span style="color:#008000">document</span>.querySelector(<span style="color:#ba2121">&#34;[data-bullpen-prompt]&#34;</span>)
  .addEventListener(<span style="color:#ba2121">&#34;click&#34;</span>, async <span style="color:#008000;font-weight:bold">function</span> (e) {
    <span style="color:#008000;font-weight:bold">var</span> response <span style="color:#666">=</span> await <span style="color:#008000">window</span>.prompt(
      <span style="color:#ba2121">&#34;Make any changes and save this prompt.&#34;</span>,
      <span style="color:#ba2121">&#34;Some default text.&#34;</span>
    );

    console.warn(response);
  });
</code></pre></div><ol start="2">
<li>Use it in the developer console on this page right now:</li>
</ol>
<div class="highlight"><pre style=";-moz-tab-size:2;-o-tab-size:2;tab-size:2"><code class="language-js" data-lang="js"><span style="color:#008000;font-weight:bold">var</span> response <span style="color:#666">=</span> await <span style="color:#008000">window</span>.prompt(
  <span style="color:#ba2121">&#34;Make any changes and save this prompt.&#34;</span>,
  <span style="color:#ba2121">&#34;Some default text.&#34;</span>
);

console.warn(response);
</code></pre></div><ol start="3">
<li>Try one of the following buttons. (Open the developer console to read the responses.)</li>
</ol>



<p>
<button type="button" data-alert-opener>Open alert()</button>
<button type="button" data-confirm-opener>Open confirm()</button>
<button type="button" data-prompt-opener>Open prompt()</button>


<h2 id="the-alert-dialog-script">The alert-dialog script</h2>
<p>View the JavaScript source file, <a href="./alert-dialog.js">alert-dialog.js</a>.</p>
]]></content:encoded>
		</item>
		
		<item>
			<title>Test Suite: SAM pattern Calculator demo</title>
			<link>https://dfkaye.com/demos/calculator/</link>
			<pubDate>Thu, 28 Jan 2021 14:38:27 -0800</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/calculator/</guid>
			
			<description><![CDATA[ Test suite and demo for an Accessible Calculator supporting keyboard navigation and input, built with CSS grid, ARIA alert, and vanilla JavaScript, using the SAM pattern and dependency injection.]]></description>
			<content:encoded><![CDATA[ <h2 id="calculator">Calculator</h2>
<p>This page contains the running calculator and the test suite used for driving and isolating the parts.</p>
<p>The 

<kbd>TAB</kbd>
 key navigates the keypad in the same key order as the Windows Calculator app.</p>
<p>The 

<kbd>Arrow</kbd>
 keys navigate the keypad by rows or columns, in the same order as the Windows Calculator app.</p>
<p>The keypad accepts click and touch events on each key.</p>
<p>The calculator container accepts focus in order to accept keyboard events.</p>
<h2 id="status">Status</h2>
<ul>
<li><em>

<time datetime="2020-12-19">December 19, 2020</time>
: Work begun in earnest.</em></li>
<li><em>

<time datetime="2021-01-08">January 8, 2021</time>
: Work in progress. Functionality still being implemented.</em></li>
<li><em>

<time datetime="2021-01-23">January 23, 2021</time>
: Tests passing; more needed; calculator app runs after 5 second delay.</em></li>
<li>

<time datetime="2021-01-27">January 27, 2021</time>
:
<ul>
<li>Getting very close now! The model logic is the most involved part, when trying to match the behavior of the Microsoft Windows Calculator.</li>
<li>Found another safe-math issue, this time <em>inside</em> <code>expand()</code> - <code>.14 * 100</code> returns <code>14.000000000000002</code> where 100 is the exponsion factor. Solve with parseInt(), fallback to previous if that results in <code>NaN</code>.</li>
<li>Covered the remaining expression update sequence issues:
<ul>
<li>(&ldquo;6 =, then 3, should print 3 =&rdquo;) // Yes!</li>
<li>(&ldquo;3 =, then +, should print 3 +&rdquo;)</li>
<li>(&ldquo;3 +, then =, should print 3 + 3 =, output is 6&rdquo;)</li>
<li>(&ldquo;7 + 8, then =, should print 7 + 8 =, output is 15&rdquo;)</li>
<li>(&ldquo;7 + 8 =, then *, should print 15 *, output is 15&rdquo;) // Yes!!!</li>
<li>(&ldquo;15 *, then 6, then =, should print 15 * 6 =, output is 90&rdquo;) // Yes!!</li>
<li>(&ldquo;15 * 6 =, then =, should print 90 * 6 =, output is 540&rdquo;)</li>
</ul>
</li>
</ul>
</li>
<li>

<time datetime="2021-01-28">January 28, 2021</time>
:
<ul>
<li><em>remove this</em>: added <code>state.history()</code> for fun</li>
<li><strong>Calling it done.  Blog post to follow.</strong></li>
</ul>
</li>
<li>

<time datetime="2021-05-20">May 20, 2021</time>
:
<ul>
<li>re-think the history part: state can generate a history for the view to store.</li>
<li>why? the view is the <em>client</em> and therefore must manage its own concerns separately from &ldquo;the state.&rdquo;</li>
</ul>
</li>
<li>

<time datetime="2021-07-14">July 14, 2021</time>
:
<ul>
<li>Bug fix for appending digits: When new value exceeds safe integer limit, do <em>not</em> append new digit.</li>
<li>Add decimal test for appending when output less than or equal safe integer limit.</li>
<li>Fix view test for <code>document.readyState</code>.</li>
</ul>
</li>
</ul>
<h3 id="blog-post-elements-to-cover">Blog post elements to cover</h3>
<ul>
<li>list of key aliases for actions (e.g., Escape for Clear, Enter and Space for a click, <code>r</code> for <code>reciprocal</code>, <code>q</code>, <code>@</code>, <code>F9</code>, and so on).</li>
<li>accessibility support - screen readers, alert text, keyboard navigation and input</li>
<li>mimmicking MS Windows Calculator expressions: output is fairly straight-forward, but the expression text logic is <strong>complicated</strong>.</li>
<li>2 safe-math bugs found</li>
<li>no update if next digit creates output greater than safe integer limit</li>
<li>appends decimal even if output at safe integer limit</li>
<li>Edge case in JavaScript numbers, MAX + 0.4 === MAX, MAX + 0.5 === MAX.5
<ul>
<li>tweet: <a href="https://twitter.com/dfkaye/status/1415520827047485442">https://twitter.com/dfkaye/status/1415520827047485442</a></li>
</ul>
</li>
<li>error states</li>
<li>explain CSS grid rules to mimic keyboard navigation in MS Windows Calculator</li>
<li>explain SAM pattern and why the calculator is based on it</li>
<li>explain Dependency injection and why the pattern uses it (tests!)</li>
<li>fix expression text overflow (layout breakages)</li>
<li>the view is the <em>client</em> and therefore must manage its own concerns separately from &ldquo;the state.&rdquo;</li>
</ul>



<div id="fixture">
<div calculator role="application" tabindex="0">
  <output expression>expression</output>
  <output output>[ Calculator not initialized. ]</output>
  <output visually-hidden role="alert" aria-live="polite" aria-atomic="false"></output>
  <div keypad>
    <button value="percent" aria-label="Percent">%</button>
    <button value="clearentry" aria-label="Clear Entry">CE</button>
    <button value="clear" aria-label="Clear">C</button>
    <button value="backspace" aria-label="Backspace">&ltdot;</button>
    <button value="reciprocal" aria-label="Reciprocal">
      <i><sup>1</sup>/x</i>
    </button>
    <button value="square" aria-label="Square">
      <i>x<sup>2</sup></i>
    </button>
    <button value="squareroot" aria-label="Square Root">
      <i><sup>2</sup>&radic;x</i>
    </button>
    <div operators>
      <button value="divide" aria-label="Divide By">&divide;</button>
      <button value="multiply" aria-label="Multiply By">&times;</button>
      <button value="plus" aria-label="Plus">&plus;</button>
      <button value="minus" aria-label="Minus">&minus;</button>
      <button value="equals" aria-label="Equals">&equals;</button>
    </div>
    <div numbers>
      <button value="0">0</button>
      <button value="1">1</button>
      <button value="2">2</button>
      <button value="3">3</button>
      <button value="4">4</button>
      <button value="5">5</button>
      <button value="6">6</button>
      <button value="7">7</button>
      <button value="8">8</button>
      <button value="9">9</button>
      <button value="decimal" aria-label="Decimal Separator">.</button>
      <button value="negate" aria-label="Positive-Negative"><sup>+</sup>/-</button>
    </div>
  </div>
</div>
</div>


<h2 id="suite">Suite</h2>
<p>Click on test names in the report below to display each assertion.</p>



<div id="mocha"></div>


]]></content:encoded>
		</item>
		
		<item>
			<title>Test Suite: SAM pattern Countdown demo</title>
			<link>https://dfkaye.com/demos/sam-pattern-test-suite/</link>
			<pubDate>Mon, 21 Dec 2020 20:06:29 -0800</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/sam-pattern-test-suite/</guid>
			
			<description><![CDATA[ Test suite and Countdown demo for a SAM pattern module that uses dependency injection and factory functions.]]></description>
			<content:encoded><![CDATA[ <p>This test suite exercises a Countdown application built with the SAM pattern.</p>
<p>The suite uses <a href="https://mochajs.org/">mocha.js</a>, <a href="https://www.chaijs.com/">chai.js</a>, module-type scripts, and ES2016 import/export syntax, and is served up by <a href="https://gohugo.io">Hugo</a>.</p>
<p>You can view the source of the test suite at <a href="https://dfkaye.com/js/demos/sam/suite.js">https://dfkaye.com/js/demos/sam/suite.js</a>.</p>
<h2 id="demo">Demo</h2>
<p>The countdown in progress is started by the test suite. You can restart the countdown at any time using the form input below.</p>



<div id="fixture">
  <p role="alert" aria-live="polite">T minus <b remaining role="alert" aria-live="assertive"></b> seconds.</p>
  <p><meter progress style="width: 100%;"></meter></p>
  <form>
    <label for="t-minus">Enter a countdown in seconds (optional)</label>
    <input id="t-minus" aria-label="Enter a countdown in seconds and press the Re-start button."/>
    <button type="submit" restart>Re-start</button>
  </form>
</div>


<h2 id="suite">Suite</h2>
<p>Click on test names in the report below to display each assertion.</p>



<div id="mocha"></div>


]]></content:encoded>
		</item>
		
		<item>
			<title>Test Suite: Data-driven testing with `wheredoc`</title>
			<link>https://dfkaye.com/demos/wheredoc-test-suite/</link>
			<pubDate>Wed, 02 Dec 2020 12:36:59 -0800</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/wheredoc-test-suite/</guid>
			
			<description><![CDATA[ Test suite for `wheredoc` data table testing module.]]></description>
			<content:encoded><![CDATA[ <p>This demo contains the test suite I used to develop the <code>wheredoc</code> module described in my post on <a href="/posts/2020/12/02/data-driven-testing-with-wheredoc/">Data-driven testing</a>.</p>
<p>The suite uses <a href="https://mochajs.org/">mocha.js</a>, <a href="https://www.chaijs.com/">chai.js</a>, module-type scripts, and ES2016 import/export syntax, and is served up by <a href="https://gohugo.io">Hugo</a>.</p>
<p>You can view the source of the test suite at <a href="https://github.com/dfkaye/wheredoc/blob/master/test/suite.js">https://github.com/dfkaye/wheredoc/blob/master/test/suite.js</a>.</p>
<h2 id="suite">Suite</h2>
<p>Click on test names in the report below to display each assertion.</p>



<div id="fixture"></div>
<div id="mocha"></div>


]]></content:encoded>
		</item>
		
		<item>
			<title>Demo: Most boring To-do list</title>
			<link>https://dfkaye.com/demos/most-boring-to-do-list/</link>
			<pubDate>Wed, 23 Sep 2020 14:52:41 -0700</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/most-boring-to-do-list/</guid>
			
			<description><![CDATA[ Very plain To-do list made from accessible HTML, modern vanilla JavaScript and minimally tolerable CSS.]]></description>
			<content:encoded><![CDATA[ <!-- raw HTML omitted -->
<p>This is a plain implementation of the &ldquo;to-do&rdquo; list applications once used to illustrate how to use <a href="https://backbonejs.org/#examples-todos">backbone.js</a> before hiring committees started using it as a code challenge to test a candidate&rsquo;s knowledge of front-end frameworks.</p>
<p>Orginally written in 2017, it has been modified to use a <code>&lt;form&gt;</code> (which created several 

<kbd>Enter</kbd>
 key form submission problems), custom HTML attributes, CSS attribute selectors, and accessibility roles and attributes.</p>
<p>Design may change further as this is not fully tested with screen readers yet.</p>




  <form todo aria-labelledby="populated-list">
    <!-- gratuitous comment -->
    <dialog role="alert" aria-live="assertive" alert-message="You have another item open. Please close it before editing another one." alert-close="Close"></dialog>
    <dialog role="alert" aria-live="assertive" save-message="This to-do item is empty. Add text to Save it, or press Remove to delete it." alert-close="Close"></dialog>    
    <h2 id="populated-list">Populated list</h2>
    <ul todo-list>
      <li item>
        <input name maxlength="100" readonly value="Show status on save (X added)">
        <button type="button" handle="edit" aria-label="edit">&#9997;</button>
        <button type="button" handle="done" aria-label="mark complete">&check;</button>
        <button type="button" handle="remove" aria-label="remove">&cross;</button>
      </li>
      <li item>
        <input name maxlength="100" readonly value="Trim value on save" done="true">
        <button type="button" handle="edit" aria-label="edit">&#9997;</button>
        <button type="button" handle="done" aria-label="mark incomplete">&check;</button>
        <button type="button" handle="remove" aria-label="remove">&cross;</button>
      </li>
    </ul>
    <p empty>List is currently empty. Add a new item below.</p>
    <button type="button" handle="add">Add item</button>
    <template item-template>
      <li>
        <label visually-hidden for="populated-list-input">Add a to-do item</label>
        <input id="populated-list-input" name maxlength="100" readonly placeholder="E.g., Add a to-do item" value>
        <button type="button" handle="edit" aria-label="edit">&#9997;</button>
        <button type="button" handle="done" aria-label="mark complete">&check;</button>
        <button type="button" handle="remove" aria-label="remove">&cross;</button>
      </li>
    </template>
  </form>

  <form todo aria-labelledby="empty-list">
    <!-- gratuitous comment -->
    <dialog role="alert" alert-message="Hold it. You have another item open. Save it before editing a new one." alert-close="Close"></dialog>
    <dialog role="alert" aria-live="assertive" save-message="This to-do item is empty. Add text to Save it, or press Remove to delete it." alert-close="Close"></dialog>
    <h2 id="empty-list">Empty list</h2>
    <ul todo-list></ul>
    <p empty>List is currently empty. Add a new item below.</p>
    <button type="button" handle="add">Add item</button>
    <template item-template>
      <li>
        <label visually-hidden for="empty-list-input">Add a to-do item</label>
        <input id="empty-list-input" name maxlength="100" readonly placeholder="E.g., Add a to-do item" value>
        <button type="button" handle="edit" aria-label="edit">&#9997;</button>
        <button type="button" handle="done" aria-label="mark complete">&check;</button>
        <button type="button" handle="remove" aria-label="remove">&cross;</button>
      </li>
    </template>
  </form>



<h2 id="sample-markup">Sample markup</h2>
<p>Here&rsquo;s the entire markup for the &ldquo;Empty&rdquo; list:</p>
<div class="highlight"><pre style=";-moz-tab-size:2;-o-tab-size:2;tab-size:2"><code class="language-html" data-lang="html">&lt;<span style="color:#008000;font-weight:bold">form</span> <span style="color:#7d9029">todo</span> <span style="color:#7d9029">aria-labelledby</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;empty-list&#34;</span>&gt;
  <span style="color:#408080;font-style:italic">&lt;!-- gratuitous comment --&gt;</span>
  &lt;<span style="color:#008000;font-weight:bold">dialog</span> <span style="color:#7d9029">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;alert&#34;</span> <span style="color:#7d9029">alert-message</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;Hold it. You have another item open. Save it before editing a new one.&#34;</span> <span style="color:#7d9029">alert-close</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;Close&#34;</span>&gt;&lt;/<span style="color:#008000;font-weight:bold">dialog</span>&gt;
  &lt;<span style="color:#008000;font-weight:bold">dialog</span> <span style="color:#7d9029">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;alert&#34;</span> <span style="color:#7d9029">aria-live</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;assertive&#34;</span> <span style="color:#7d9029">save-message</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;This to-do item is empty. Add text to Save it, or press Remove to delete it.&#34;</span> <span style="color:#7d9029">alert-close</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;Close&#34;</span>&gt;&lt;/<span style="color:#008000;font-weight:bold">dialog</span>&gt;  
  &lt;<span style="color:#008000;font-weight:bold">h2</span> <span style="color:#7d9029">id</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;empty-list&#34;</span>&gt;Empty list&lt;/<span style="color:#008000;font-weight:bold">h2</span>&gt;
  &lt;<span style="color:#008000;font-weight:bold">ul</span> <span style="color:#7d9029">todo-list</span>&gt;&lt;/<span style="color:#008000;font-weight:bold">ul</span>&gt;
  &lt;<span style="color:#008000;font-weight:bold">p</span> <span style="color:#7d9029">empty</span>&gt;List is currently empty. Add a new item below.&lt;/<span style="color:#008000;font-weight:bold">p</span>&gt;
  &lt;<span style="color:#008000;font-weight:bold">button</span> <span style="color:#7d9029">type</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;button&#34;</span> <span style="color:#7d9029">handle</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;add&#34;</span>&gt;Add item&lt;/<span style="color:#008000;font-weight:bold">button</span>&gt;
  &lt;<span style="color:#008000;font-weight:bold">template</span> <span style="color:#7d9029">item-template</span>&gt;
    &lt;<span style="color:#008000;font-weight:bold">li</span>&gt;
      &lt;<span style="color:#008000;font-weight:bold">label</span> <span style="color:#7d9029">visually-hidden</span> <span style="color:#7d9029">for</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;empty-list-input&#34;</span>&gt;Add a to-do item&lt;/<span style="color:#008000;font-weight:bold">label</span>&gt;
      &lt;<span style="color:#008000;font-weight:bold">input</span> <span style="color:#7d9029">id</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;empty-list-input&#34;</span> <span style="color:#7d9029">name</span> <span style="color:#7d9029">maxlength</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;100&#34;</span> <span style="color:#7d9029">readonly</span> <span style="color:#7d9029">placeholder</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;E.g., Add a to-do item&#34;</span> <span style="color:#7d9029">value</span>&gt;
      &lt;<span style="color:#008000;font-weight:bold">button</span> <span style="color:#7d9029">type</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;button&#34;</span> <span style="color:#7d9029">handle</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;edit&#34;</span> <span style="color:#7d9029">aria-label</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;edit&#34;</span>&gt;<span style="color:#999;font-weight:bold">&amp;#9997;</span>&lt;/<span style="color:#008000;font-weight:bold">button</span>&gt;
      &lt;<span style="color:#008000;font-weight:bold">button</span> <span style="color:#7d9029">type</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;button&#34;</span> <span style="color:#7d9029">handle</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;done&#34;</span> <span style="color:#7d9029">aria-label</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;mark complete&#34;</span>&gt;<span style="color:#999;font-weight:bold">&amp;check;</span>&lt;/<span style="color:#008000;font-weight:bold">button</span>&gt;
      &lt;<span style="color:#008000;font-weight:bold">button</span> <span style="color:#7d9029">type</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;button&#34;</span> <span style="color:#7d9029">handle</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;remove&#34;</span> <span style="color:#7d9029">aria-label</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;remove&#34;</span>&gt;<span style="color:#999;font-weight:bold">&amp;cross;</span>&lt;/<span style="color:#008000;font-weight:bold">button</span>&gt;
    &lt;/<span style="color:#008000;font-weight:bold">li</span>&gt;
  &lt;/<span style="color:#008000;font-weight:bold">template</span>&gt;
&lt;/<span style="color:#008000;font-weight:bold">form</span>&gt;
</code></pre></div><h2 id="css-and-javascript-sources">CSS and JavaScript sources</h2>
<ul>
<li>View the <a href="./to-do.css">CSS</a></li>
<li>View the <a href="./to-do.js">JavaScript</a></li>
</ul>
]]></content:encoded>
		</item>
		
		<item>
			<title>Demo: Accessible CSS-driven Tabs</title>
			<link>https://dfkaye.com/demos/accessible-css-driven-tabs-demo/</link>
			<pubDate>Sun, 23 Aug 2020 15:30:43 -0700</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/accessible-css-driven-tabs-demo/</guid>
			
			<description><![CDATA[ Working demo of tabbed content using CSS, no JavaScript, responsive to screen widths, and accessible to keyboard navigation and screen readers.]]></description>
			<content:encoded><![CDATA[ <h2 id="navigating-the-tabs-and-panels">Navigating the tabs and panels</h2>



<ul aria-hidden="true">
  <li>Focus on a tab by clicking with the mouse or using the <kbd>Tab</kbd> key to navigate to the tab list.</li>
  <li>You can navigate among the tabs by pressing the <kbd>ArrowDown</kbd> and <kbd>ArrowUp</kbd> keys.</li>
  <li>To focus on content of the selected tab, press the <kbd>Tab</kbd> key.</li>
  <li>To return focus from the content to the tab group, press <kbd>Shift</kbd> + <kbd>Tab</kbd>.</li>
</ul>

<ul visually-hidden>
  <li><em>Screen readers:</em> Only tested with Windows Narrator.</li>
  <li>Navigate tabs by the <kbd>ArrowDown</kbd> and<kbd>ArrowUp</kbd> keys.
    <del>each requires 2 presses to hop from radio to radio.</del></li>
  <li>

<em><time datetime="2020-08-22">August 22, 2020, 4 PM PDT</time></em>
: Arrow navigation between tabs is fixed by setting labels as
    aria-hidden, and aria-labelledby on each radio instead.</li>
  <li>To select a tab, press <kbd>Enter</kbd> or <kbd>Space</kbd>.</li>
  <li>To focus on content of a <strong>selected</strong> tab, press the <kbd>Tab</kbd> key once.</li>
  <li><em>Firefox only:</em> To focus on content of a <strong>newly selected</strong> tab, <em>double press the
      <kbd>Tab</kbd> key</em>.</li>
  <li>You can also navigate through the tabs with the <kbd>ArrowDown</kbd> key to get to the currently opened
    tab-panel content.</li>
  <li>To return focus from the content to the tab group, press <kbd>Shift</kbd> + <kbd>Tab</kbd>.</li>
</ul>

<div demo="tabs" role="tablist" aria-labelledby="tabs-demo-heading">
  <h2 id="tabs-demo-heading" tabs-demo-heading>Demo</h2>

  <input name="tabs" type="radio" id="tab-1" aria-labelledby="tab-label-1" aria-roledescription="tab" checked>
  <label role="tab" for="tab-1" id="tab-label-1" aria-hidden="true">Tab 1</label>

  <input name="tabs" type="radio" id="tab-2" aria-labelledby="tab-label-2" aria-roledescription="tab">
  <label role="tab" for="tab-2" id="tab-label-2" aria-hidden="true">Tab 2</label>

  <input name="tabs" type="radio" id="tab-3" aria-labelledby="tab-label-3" aria-roledescription="tab">
  <label role="tab" for="tab-3" id="tab-label-3" aria-hidden="true">Tab 3</label>

  <input name="tabs" type="radio" id="tab-4" aria-labelledby="tab-label-4" aria-roledescription="tab">
  <label role="tab" for="tab-4" id="tab-label-4" aria-hidden="true">Tab 4</label>

  <input name="tabs" type="radio" id="tab-5" aria-labelledby="tab-label-5" aria-roledescription="tab">
  <label role="tab" for="tab-5" id="tab-label-5" aria-hidden="true">Tab 5</label>

  <input name="tabs" type="radio" id="tab-6" aria-labelledby="tab-label-6" aria-roledescription="tab">
  <label role="tab" for="tab-6" id="tab-label-6" aria-hidden="true">Tab 6</label>

  <div role="tabpanel" aria-labelledby="tab-label-1">
    <h3 tabindex="0">Tab panel 1</h3>
    <p>Very little content.</p>
  </div>

  <div role="tabpanel" aria-labelledby="tab-label-2">
    <h3 tabindex="0">Tab panel 2</h3>

    <h4>A list of items.</h4>
    <ul>
      <li>first</li>
      <li>second</li>
      <li>third</li>
    </ul>
  </div>

  <div role="tabpanel" aria-labelledby="tab-label-3">
    <h3 tabindex="0">Tab panel 3</h3>

    <!-- from https://lipsum.com/ -->
    <h4>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC</h4>

    <blockquote lang="la">
      Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem
      aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo
      enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui
      ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur,
      adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat
      voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut
      aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil
      molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
    </blockquote>
  </div>

  <div role="tabpanel" aria-labelledby="tab-label-4">
    <h3 tabindex="0">Tab panel 4</h3>
    <h4>A code sample</h4>
    <pre><code>// 16 October 2019
// Modified version from tweet by @etoxin
// "I like to call this unloading a website."
// https://twitter.com/etoxin/status/1179644600522162176

Array.from(
  document.querySelectorAll('*')
)
.reverse()
.forEach(async (n, t) => {
  await setTimeout(() => {
    n.remove();
  }, t * 10);
});</code>
  </pre>
  </div>

  <div role="tabpanel" aria-labelledby="tab-label-5">
    <h3 tabindex="0">Tab panel 5</h3>
    <label for="text-area">A text area</label>
    <br>
    <textarea id="text-area"></textarea>
  </div>

  <div role="tabpanel" aria-labelledby="tab-label-6">
    <h3 tabindex="0">Tab panel 6</h3>
    <table>
      <caption>An unstyled table, with a caption</caption>
      <thead>
        <th scope="col">Name</th>
        <th scope="col">Rank</th>
        <th scope="col">Serial number</th>
      </thead>
      <tfoot>
        <tr>
          <td>&copy; 2020</td>
        </tr>
      </tfoot>
      <tbody>
        <tr>
          <td scope="row">Kim Jorgenson</td>
          <td>Manager</td>
          <td>[redacted]</td>
        </tr>
        <tr>
          <td scope="row">david kaye</td>
          <td>lowercase lieutenant</td>
          <td>8925604623920945230</td>
        </tr>        
      </tbody>            
    </table>
  </div>      
</div>


<h2 id="details">Details</h2>
<p>You can read the accompanying blog post explaining the solution at <a href="https://dfkaye.com/posts/2020/08/23/accessible-css-driven-tabs-without-javascript/">https://dfkaye.com/posts/2020/08/23/accessible-css-driven-tabs-without-javascript/</a>.</p>
<h2 id="css">CSS</h2>
<div class="highlight"><pre style=";-moz-tab-size:2;-o-tab-size:2;tab-size:2"><code class="language-css" data-lang="css"><span style="color:#408080;font-style:italic">/* Container holding all contents. */</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tablist&#34;</span><span style="color:#666">]</span> {
  <span style="color:#408080;font-style:italic">/* 1 Sept 2020: ADDED flex to remove media query */</span>
  <span style="color:#008000;font-weight:bold">display</span>: <span style="color:#008000;font-weight:bold">flex</span>;
  <span style="color:#008000;font-weight:bold">flex-wrap</span>: <span style="color:#008000;font-weight:bold">wrap</span>;    
}

<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">tabs-demo-heading</span><span style="color:#666">]</span> {
  <span style="color:#408080;font-style:italic">/* 1 Sept 2020: Added due to flexbox solution; need 100% width. */</span>
  <span style="color:#008000;font-weight:bold">flex-basis</span>: <span style="color:#666">100</span><span style="color:#b00040">%</span>;    
}

<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span> {
  <span style="color:#408080;font-style:italic">/* Do not hide the radio elements, make them invisible. */</span>
  <span style="color:#008000;font-weight:bold">opacity</span>: <span style="color:#666">0</span>;
  <span style="color:#008000;font-weight:bold">position</span>: <span style="color:#008000;font-weight:bold">absolute</span>;    
}

<span style="color:#408080;font-style:italic">/* The main tab headings */</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">]</span> {
  <span style="color:#008000;font-weight:bold">background</span>: <span style="color:#008000;font-weight:bold">white</span>;

  <span style="color:#408080;font-style:italic">/* base border style here; set color in :checked, style in :focus */</span>
  <span style="color:#008000;font-weight:bold">border-color</span>: <span style="color:#008000;font-weight:bold">transparent</span>;
  <span style="color:#008000;font-weight:bold">border-style</span>: <span style="color:#008000;font-weight:bold">solid</span>;
  <span style="color:#008000;font-weight:bold">border-width</span>: <span style="color:#666">1</span><span style="color:#b00040">px</span> <span style="color:#666">1</span><span style="color:#b00040">px</span> <span style="color:#666">0</span>;

  <span style="color:#008000;font-weight:bold">box-shadow</span>: <span style="color:#008000;font-weight:bold">inset</span> <span style="color:#666">0</span> <span style="color:#666">-0.5</span><span style="color:#b00040">em</span> <span style="color:#666">0.5</span><span style="color:#b00040">em</span> <span style="color:#008000">rgba</span>(<span style="color:#666">0</span>, <span style="color:#666">0</span>, <span style="color:#666">0</span>, <span style="color:#666">0.02</span>);
  <span style="color:#008000;font-weight:bold">color</span>: <span style="color:#008000;font-weight:bold">lightgrey</span>;
  <span style="color:#008000;font-weight:bold">cursor</span>: <span style="color:#008000;font-weight:bold">pointer</span>;
  <span style="color:#008000;font-weight:bold">display</span>: <span style="color:#008000;font-weight:bold">inline</span><span style="color:#666">-</span><span style="color:#008000;font-weight:bold">block</span>;
  <span style="color:#008000;font-weight:bold">font-weight</span>: <span style="color:#666">600</span>;

  <span style="color:#408080;font-style:italic">/* hides the bottom border */</span>
  <span style="color:#008000;font-weight:bold">margin-bottom</span>: <span style="color:#666">-1</span><span style="color:#b00040">px</span>;

  <span style="color:#408080;font-style:italic">/* 1 Sept 2020: removed to let flex apply gaps. */</span>
  <span style="color:#408080;font-style:italic">/* margin-right: 5px; */</span>

  <span style="color:#008000;font-weight:bold">padding</span>: <span style="color:#666">10</span><span style="color:#b00040">px</span> <span style="color:#666">20</span><span style="color:#b00040">px</span>;
  <span style="color:#008000;font-weight:bold">text-align</span>: <span style="color:#008000;font-weight:bold">center</span>;
  <span style="color:#008000;font-weight:bold">transition</span>: <span style="color:#008000;font-weight:bold">all</span> <span style="color:#666">0.2</span><span style="color:#b00040">s</span> <span style="color:#008000;font-weight:bold">ease</span>;

  <span style="color:#408080;font-style:italic">/* 1 Sept 2020: ADDED flex attributes to remove media query */</span>
  <span style="color:#008000;font-weight:bold">flex-basis</span>: <span style="color:#666">5</span><span style="color:#b00040">em</span>;
  <span style="color:#008000;font-weight:bold">flex-shrink</span>: <span style="color:#666">1</span>;
  <span style="color:#008000;font-weight:bold">flex-grow</span>: <span style="color:#666">1</span>;
}

<span style="color:#408080;font-style:italic">/* Style the currently selected tab label */</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">checked</span> <span style="color:#666">+</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">]</span> {
  <span style="color:#408080;font-style:italic">/* ADDED */</span>
  <span style="color:#008000;font-weight:bold">border-color</span>: <span style="color:#666">#eee</span>;

  <span style="color:#008000;font-weight:bold">box-shadow</span>: <span style="color:#666">0</span> <span style="color:#666">-6</span><span style="color:#b00040">px</span> <span style="color:#666">8</span><span style="color:#b00040">px</span> <span style="color:#008000">rgba</span>(<span style="color:#666">0</span>, <span style="color:#666">0</span>, <span style="color:#666">0</span>, <span style="color:#666">0.02</span>);
  <span style="color:#008000;font-weight:bold">color</span>: <span style="color:#666">#268bd2</span>;

  <span style="color:#408080;font-style:italic">/* 1 Sept 2020: ADDED here with flexbox solution, removing the media query. */</span>
  <span style="color:#008000;font-weight:bold">margin-bottom</span>: <span style="color:#666">0</span>;
}

<span style="color:#408080;font-style:italic">/*
</span><span style="color:#408080;font-style:italic">  ADDED: give tab a focus style.
</span><span style="color:#408080;font-style:italic">  This selector has the same specificity as the :checked selector, so it
</span><span style="color:#408080;font-style:italic">  should appear later in the source order to insure it takes effect.
</span><span style="color:#408080;font-style:italic">  */</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">focus</span> <span style="color:#666">+</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">],</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">hover</span> <span style="color:#666">+</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">]</span> {
  <span style="color:#008000;font-weight:bold">text-decoration</span>: <span style="color:#008000;font-weight:bold">underline</span>;
}

<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">focus</span> <span style="color:#666">+</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">]</span> {
  <span style="color:#008000;font-weight:bold">border-color</span>: <span style="color:#666">#268bd2</span>;
  <span style="color:#008000;font-weight:bold">border-style</span>: <span style="color:#008000;font-weight:bold">dotted</span>;
}

<span style="color:#408080;font-style:italic">/* The inner tab content */</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span> {
  <span style="color:#008000;font-weight:bold">background</span>: <span style="color:#008000;font-weight:bold">white</span>;

  <span style="color:#408080;font-style:italic">/* pulled up from the :checked state sibling ruleset below */</span>
  <span style="color:#008000;font-weight:bold">border</span>: <span style="color:#666">1</span><span style="color:#b00040">px</span> <span style="color:#008000;font-weight:bold">solid</span> <span style="color:#666">#eee</span>;

  <span style="color:#008000;font-weight:bold">box-shadow</span>: <span style="color:#666">0</span> <span style="color:#666">6</span><span style="color:#b00040">px</span> <span style="color:#666">8</span><span style="color:#b00040">px</span> <span style="color:#008000">rgba</span>(<span style="color:#666">0</span>, <span style="color:#666">0</span>, <span style="color:#666">0</span>, <span style="color:#666">0.02</span>);

  <span style="color:#408080;font-style:italic">/* ADDED: Hide panels by default */</span>
  <span style="color:#008000;font-weight:bold">display</span>: <span style="color:#008000;font-weight:bold">none</span>;

  <span style="color:#008000;font-weight:bold">padding</span>: <span style="color:#666">20</span><span style="color:#b00040">px</span>;
  <span style="color:#008000;font-weight:bold">transition</span>: <span style="color:#008000;font-weight:bold">all</span> <span style="color:#666">0.2</span><span style="color:#b00040">s</span> <span style="color:#008000;font-weight:bold">ease</span>;

  <span style="color:#408080;font-style:italic">/* 1 Sept 2020: ADDED flex attr to stretch panel 100% width. */</span>
  <span style="color:#008000;font-weight:bold">flex-basis</span>: <span style="color:#666">100</span><span style="color:#b00040">%</span>;
}

<span style="color:#408080;font-style:italic">/*
</span><span style="color:#408080;font-style:italic">  Verbose state-machine-like part:
</span><span style="color:#408080;font-style:italic">  - z-index, position, and overflow no longer needed,
</span><span style="color:#408080;font-style:italic">  - allows document content to flow in source order.
</span><span style="color:#408080;font-style:italic">*/</span>

<span style="color:#408080;font-style:italic">/* Show the currently selected tab content */</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">1</span><span style="color:#666">)</span>:<span style="color:#a2f">checked</span> <span style="color:#666">~</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">1</span><span style="color:#666">),</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">2</span><span style="color:#666">)</span>:<span style="color:#a2f">checked</span> <span style="color:#666">~</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">2</span><span style="color:#666">),</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">3</span><span style="color:#666">)</span>:<span style="color:#a2f">checked</span> <span style="color:#666">~</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">3</span><span style="color:#666">),</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">4</span><span style="color:#666">)</span>:<span style="color:#a2f">checked</span> <span style="color:#666">~</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">4</span><span style="color:#666">),</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">5</span><span style="color:#666">)</span>:<span style="color:#a2f">checked</span> <span style="color:#666">~</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">5</span><span style="color:#666">),</span>
<span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">6</span><span style="color:#666">)</span>:<span style="color:#a2f">checked</span> <span style="color:#666">~</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabpanel&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">nth-of-type</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">6</span><span style="color:#666">)</span> {
  <span style="color:#408080;font-style:italic">/* ADDED: show selected tabpanel */</span>
  <span style="color:#008000;font-weight:bold">display</span>: <span style="color:#008000;font-weight:bold">block</span>;
}

<span style="color:#408080;font-style:italic">/* 1 Sept 2020: media query no longer used. */</span>
@<span style="color:#008000;font-weight:bold">media</span><span style="color:#666">(</span><span style="color:#008000;font-weight:bold">max-width</span>:<span style="color:#a2f">38em</span><span style="color:#666">)</span> {
  <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">]</span> {
    <span style="color:#408080;font-style:italic">/* display: block; */</span>

    <span style="color:#408080;font-style:italic">/* ADDED - tabs no longer need right margin */</span>
    <span style="color:#408080;font-style:italic">/* margin-right: 0; */</span>

    <span style="color:#408080;font-style:italic">/* ADDED - &#34;unhide&#34; the bottom margin */</span>
    <span style="color:#408080;font-style:italic">/* MOVED TO checked + tab rule *?
</span><span style="color:#408080;font-style:italic">    /* margin-bottom: 0; */</span>
  }

  <span style="color:#408080;font-style:italic">/* ADDED: for visual emphasis. */</span>
  <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">name</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tabs&#34;</span><span style="color:#666">]</span>:<span style="color:#a2f">checked</span> <span style="color:#666">+</span> <span style="color:#666">[</span><span style="color:#008000;font-weight:bold">role</span><span style="color:#666">=</span><span style="color:#ba2121">&#34;tab&#34;</span><span style="color:#666">]</span> {
    <span style="color:#408080;font-style:italic">/* 1 Sept 2020: REMOVED due to flexbox solution */</span>
    <span style="color:#408080;font-style:italic">/* border-bottom: 1px solid #eee; */</span>
  }
}

</code></pre></div>]]></content:encoded>
		</item>
		
		<item>
			<title>Test suite: Safe assign wrapper for Object.assign()</title>
			<link>https://dfkaye.com/demos/safe-assign-test-suite/</link>
			<pubDate>Fri, 21 Aug 2020 11:56:43 -0700</pubDate><dc:creator>David F. Kaye</dc:creator>
			<guid>https://dfkaye.com/demos/safe-assign-test-suite/</guid>
			
			<description><![CDATA[ Test suite for safe-object-assign.js module.]]></description>
			<content:encoded><![CDATA[ <p>This demo contains the test suite I used to drive the safe-assign.js module described in my post on <a href="/posts/2020/08/21/safer-object.assign-operations-using-a-sensible-wrapper/">Safer Object.assign() operations</a>.</p>
<p>The suite uses <a href="https://mochajs.org/">mocha.js</a>, <a href="https://www.chaijs.com/">chai.js</a>, module-type scripts, and ES2016 import/export syntax, and is served up by <a href="https://gohugo.io">Hugo</a>.</p>
<p>You can view the source of the test suite at <a href="https://github.com/dfkaye/safe-object-assign/blob/main/test/browser-suite.js">https://github.com/dfkaye/safe-object-assign/blob/main/test/browser-suite.js</a>.</p>
<h2 id="suite">Suite</h2>
<p>Click on test names in the report below to display each assertion.</p>



<div id="fixture"></div>
<div id="mocha"></div>


]]></content:encoded>
		</item>
		
	</channel>
</rss>
