FACE - radio button example

by int32_t

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.
  formStateRestoreCallback(state, mode) {
    this.checked = state == 'on';
  }

  get checked() { return this.checked_; }
  set checked(flag) {
    this.checked_ = flag;
    if (flag) {
      let value = this.getAttribute('value');
      this.internals_.setFormValue(value ? value : 'on', 'on');
    } else {
      this.internals_.setFormValue(null, 'off');
    }
    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_();
    
    this.updateValidityOfGroupMembers_(this.form_, this.name);
    this.updateValidityOfGroupMembers_(nullableForm, this.name);
    this.form_ = nullableForm;
  }

  updateView_() {
    this.textContent = this.checked ? '\u{1F518}' : '\u26AA';
    if...