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_();
    
   ...