Skip to content

Instantly share code, notes, and snippets.

@agektmr
Last active September 11, 2020 09:58
Show Gist options
  • Save agektmr/67dce7e9db26c48b5ddc6811fb95d02d to your computer and use it in GitHub Desktop.
Save agektmr/67dce7e9db26c48b5ddc6811fb95d02d to your computer and use it in GitHub Desktop.
`input[autocomplete="one-time-code"]` polyfill using Web OTP API
if ('customElements' in window && 'OTPCredential' in window) {
  customElements.define("web-otp",
    class extends HTMLInputElement {
      connectedCallback() {
        this.abortController = new AbortController();
        this.receive(); 
      }
      disconnectedCallback() {
        this.abort();
      }
      abort() {
        this.abortController.abort();
      }
      async receive() {
        try {
          const content = await navigator.credentials.get({
            otp: {transport:['sms']}, signal: this.abortController.signal
          });
          this.value = content.code;
          this.dispatchEvent(new Event('autocomplete'));
        } catch (e) {
          console.error(e);
        }
      }
    }, {
      extends: "input"
  });
}
@samthor
Copy link

samthor commented Apr 14, 2020

Thoughts:

  • Rename this.signal to this.abortController
  • navigator.credentials.get accepts signal, not abort, and you then want to pass the .signal property of the AbortController
    • The point is you hold onto AbortController so you can abort it, but only give out the AbortSignal to things that get aborted
  • IIRC Safari doesn't support extending anything but HTMLElement, I'm not sure where the polyfill is for—Chrome or somewhere else?

@agektmr
Copy link
Author

agektmr commented Apr 14, 2020

  • Replaced this.signal with this.abortController
  • Replaced .abort property with .signal. It was a spec issue.

Regarding "polyfill", this is more of making Chrome to work like Safari's declarative behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment