Last active
June 10, 2020 16:02
-
-
Save dfkaye/612d34a66b9bb74efc29 to your computer and use it in GitHub Desktop.
traffic signal HTML test for 11 June, completed 12 June 2015, simplified 5 Sep 2015
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- | |
click <next> to change signal lamp from red to green to yellow to red to... | |
simplified 5-6 Sep 2015 | |
+ reset signal attribute on parent element (single value state) | |
+ let state rules define which lamp is colored. | |
31 Oct 2016 | |
+ prefixed attributes with "data-" per the HTML5 Spec... | |
28 Aug 2017 | |
+ changes attrs from [data-lamp][data-stop] to [data-lamp="stop"] | |
--> | |
<title>traffic signal test revised</title> | |
<style> | |
[data-signal] { | |
background: grey; | |
display: inline-block; | |
margin: 0; | |
outline: 1px solid; | |
padding: 0; | |
} | |
[data-lamp] { | |
background: #adadad; | |
border-radius: 2em 2em; /* make circular :) */ | |
border: 1px solid; | |
height: 3em; | |
list-style-type: none; | |
margin: 1em; | |
padding: 0; | |
width: 3em; | |
} | |
[data-signal="stop"] [data-lamp="stop"] { background: red; } | |
[data-signal="slow"] [data-lamp="slow"] { background: yellow; } | |
[data-signal="go"] [data-lamp="go"] { background: green; } | |
[data-next] { | |
/* force newline after inline traffic list */ | |
display:block; | |
} | |
</style> | |
<ul data-signal> | |
<li data-lamp="stop"></li> | |
<li data-lamp="slow"></li> | |
<li data-lamp="go"></li> | |
</ul> | |
<button type="button" data-next>next</button> | |
<script> | |
!(function() { | |
var signal = document.querySelector('[data-signal]') | |
var btn = document.querySelector('[data-next]') | |
var lamp; // store state here, no need to call signal.getAttribute | |
function next() { | |
lamp = (lamp == 'stop' ? 'go' : (lamp == 'go' ? 'slow' : 'stop')) | |
signal.setAttribute('data-signal', lamp) | |
} | |
next() | |
btn.addEventListener('click', next) | |
}()); | |
</script> | |
<p> | |
Click `[next]` to change signal lamp from red to green to yellow to red to... | |
</p> | |
<p> | |
HTML uses no `class` attributes - instead uses custom attributes (prefixed | |
with "data-") - CSS uses attribute selectors - JS uses | |
querySelector('[data-attr-name]') and `.setAttribute(value)` | |
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- | |
click <change> to change signal lamp from red to green to yellow to red to... | |
simplified 5-6 Sep 2015 | |
+ reset signal attribute on parent element (single value state) | |
+ let state rules define which lamp is colored. | |
31 Oct 2016 | |
+ prefixed attributes with "data-" per the HTML5 Spec... | |
--> | |
<title>traffic signal test revised</title> | |
<style> | |
[data-signal] { | |
background: grey; | |
display: inline-block; | |
margin: 0; | |
outline: 1px solid; | |
padding: 0; | |
} | |
[data-lamp] { | |
background: #adadad; | |
border-radius: 2em 2em; /* make circular :) */ | |
border: 1px solid; | |
height: 3em; | |
list-style-type: none; | |
margin: 1em; | |
padding: 0; | |
width: 3em; | |
} | |
[data-signal='stop'] [data-stop] { background: red; } | |
[data-signal='slow'] [data-slow] { background: yellow; } | |
[data-signal='go'] [data-go] { background: green; } | |
[data-change] { | |
/* force newline after inline traffic list */ | |
display:block; | |
} | |
</style> | |
<ul data-signal> | |
<li data-lamp data-stop></li> | |
<li data-lamp data-slow></li> | |
<li data-lamp data-go></li> | |
</ul> | |
<button data-change>change</button> | |
<script> | |
!(function() { | |
var signal = document.querySelector('[data-signal]') | |
var btn = document.querySelector('[data-change]') | |
var lamp; // store state here, no need to call signal.getAttribute | |
function change() { | |
lamp = (lamp == 'stop' ? 'go' : (lamp == 'go' ? 'slow' : 'stop')) | |
signal.setAttribute('data-signal', lamp) | |
} | |
change() | |
btn.addEventListener('click', change) | |
}()); | |
</script> | |
<p> | |
Click `[change]` to change signal lamp from red to green to yellow to red to... | |
</p> | |
<p> | |
HTML uses no `class` attributes - instead uses custom attributes (prefixed | |
with "data-") - CSS uses attribute selectors - JS uses | |
querySelector('[data-attr-name]') and `.setAttribute(value)` | |
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- | |
click <change> to change signal lamp from red to green to yellow to red to... | |
simplified 5 Sep 2015 | |
+ reset signal attribute on parent element (single value state) | |
+ let state rules define which lamp is colored. | |
--> | |
<title>traffic signal test revised</title> | |
<style> | |
[signal] { | |
background: grey; | |
display: inline-block; | |
margin: 0; | |
outline: 1px solid; | |
padding: 0; | |
} | |
[lamp] { | |
background: #adadad; | |
border-radius: 2em 2em; /* make circular :) */ | |
border: 1px solid; | |
height: 3em; | |
list-style-type: none; | |
margin: 1em; | |
padding: 0; | |
width: 3em; | |
} | |
[signal='stop'] [stop] { background: red; } | |
[signal='slow'] [slow] { background: yellow; } | |
[signal='go'] [go] { background: green; } | |
[change] { | |
/* force newline after inline traffic list */ | |
display: block; | |
} | |
</style> | |
<ul signal> | |
<li lamp stop></li> | |
<li lamp slow></li> | |
<li lamp go></li> | |
</ul> | |
<button change>change</button> | |
<script> | |
!(function() { | |
var signal = document.querySelector('[signal]') | |
var btn = document.querySelector('[change]') | |
var lamp; // store state here, no need to call signal.getAttribute | |
function change() { | |
// decision algorithm for next state | |
lamp = (lamp == 'stop' ? 'go' : (lamp == 'go' ? 'slow' : 'stop')) | |
signal.setAttribute('signal', lamp) | |
} | |
change() // initialize... | |
btn.addEventListener('click', change) | |
}()); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- | |
click <next> to change signal from red to green to yellow to red to... | |
completed version of this test by @dfkaye 12 June 2015 using | |
+ multiple attribute selectors | |
+ array.some() method for early iteration exit | |
+ omitted html, head and body tags ~ browsers insert these on parse! | |
--> | |
<title>traffic signal test</title> | |
<style> | |
[traffic] { | |
background: grey; | |
display: inline-block; | |
margin: 0; | |
outline: 1px solid; | |
padding: 0; | |
text-align: center; | |
} | |
[signal] { | |
background: #adadad; | |
border-radius: 2em 2em; /* make circular :) */ | |
border: 1px solid; | |
height: 3em; | |
list-style-type: none; | |
margin: 1em; | |
padding: 0; | |
width: 3em; | |
} | |
/* select by presence of multiple attributes */ | |
/* an active signal shows its color */ | |
[active][stop] { background: red; } | |
[active][slow] { background: yellow; } | |
[active][go] { background: green; } | |
[next] { | |
/* force newline after inline traffic list */ | |
display: block; | |
} | |
</style> | |
<ul traffic> | |
<li stop signal active></li><!-- default --> | |
<li slow signal></li> | |
<li go signal></li> | |
</ul> | |
<button next>next</button> | |
<script> | |
!(function() { | |
var signals = [].slice.call(document.querySelectorAll('[signal]')); | |
var btn = document.querySelector('[next]'); | |
var active = document.querySelector('[signal][active]') || signals[0]; | |
var handleClick = function handleClick(e) { | |
var next; | |
signals.some(function (signal, i) { | |
return signal === active && (next = signals[i === 0 ? signals.length - 1 : i - 1]); | |
}); | |
active.removeAttribute('active'); | |
next.setAttribute('active', ''); | |
active = next; | |
}; | |
btn.addEventListener('click', handleClick); | |
}()); | |
</script> |
The revised next
algorithm in the revised file came to me unexpectedly, and may change the way I approach anything from now on. It feels more like a breakthrough than it really is due to its simplicity, which I prefer over the gratuitous chaining that functional programming seems to demand.
lamp = (lamp == 'stop' ? 'go' :
(lamp == 'go' ? 'slow' :
'stop'))
Real benefits:
- easier to type (only possible choices are 'go', 'slow' or 'stop')
- involves no functional iterator callback dependency because we don't iterate over lamp elements
- sets the attribute only on the signal element
- never reads from the signal element (no element.getAttribute() or removeAttribute() calls)
- the decision sequence allows for an initial call to set a default state (i.e., to 'stop')
- the attribute-based CSS uses a single-value attribute (signal) as a state on the ancestor to each lamp type attributes (go, slow, stop)
Possible TODO:
- [role='tab'][aria-selected] for #a11y
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Alternative JavaScript w/IIFE in array#some() w/IIFE: