FACE - radio button example
HTML
<form action="https://httpbin.org/post" method=post target=_new>
<fieldset>
<label><my-radio name=foo value="r1" tabindex=0></my-radio> Label 1</label>
<label><my-radio name=foo value="r2" tabindex=0></my-radio> Label 2</label>
<label><my-radio name=foo value="r3" tabindex=0 required></my-radio> Label 3</label>
</fieldset>
<input type=submit>
</form>
<pre></pre>
CSS
my-radio:invalid {
background-color: #f88;
}
my-radio:disabled {
background: gray;
}
my-radio {
display: inline-block;
width: 24px;
height: 24px;
}
JavaScript
function log(str) {
document.querySelector('pre').textContent += str + '\n';
}
class MyControl extends HTMLElement {
static get formAssociated() { return true; }
static get observedAttributes() { return ['name', 'required']; }
constructor() {
super();
this.internals_ = this.attachInternals();
this.checked = false;
this.addEventListener('click', this.onClick_.bind(this));
}
get form() { return this.internals_.form; }
get name() { return this.getAttribute('name'); }
get type() { return this.localName; }
get value() { return this.getAttribute('value'); }
checkValidity() {
return this.internals_.checkValidity();
}
// This is called by UA.
// FIXME: Should rename this.
restoreValueCallback(v) {
this.checked = !!v;
}
get checked() { return this.checked_; }
set checked(flag) {
this.checked_ = flag;
if (flag) {
let fd = new FormData();
if (this.name)
fd.append(this.name, this.getAttribute('value'));
// 'on' is for telling the current state to the UA.
// fd is for form submission.
this.internals_.setFormValue('on', fd);
} else {
// FIXME: This should drop name= from query string. The Chrome Canary
// as of 2018-12 adds name=.
this.internals_.setFormValue('', new FormData());
}
if (this.isConnected)
this.updateView_();
if (flag)
this.uncheckOtherGroupMembers_();
}
attributeChangedCallback(attrName, oldValue, newValue) {
if (attrName == 'required')
this.updateValidityOfGroupMembers_(this.internals_.form, this.name);
else if (attrName == 'name') {
this.updateValidityOfGroupMembers_(this.internals_.form, oldValue);
this.updateValidityOfGroupMembers_(this.internals_.form, newValue);
}
}
connectedCallback() {
this.updateView_();
}
formAssociatedCallback(nullableForm) {
if (this.checked)
this.uncheckOtherGroupMembers_();
...