Created
October 7, 2020 21:03
-
-
Save RoXuS/390950549dbc29aac593f8b96095308b to your computer and use it in GitHub Desktop.
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
/* eslint-disable no-multi-assign */ | |
interface InputWrapper { | |
input?: HTMLInputElement; | |
inputListener?: () => void; | |
proxy?: HTMLInputElement; | |
proxyListener?: () => void; | |
} | |
const SUBMIT = 'submit'; | |
const INPUT = 'input'; | |
const username: InputWrapper = {}; | |
const password: InputWrapper = {}; | |
const proxyForm = document.createElement('form'); | |
const createInput = () => document.createElement('input'); | |
const hide = (element: HTMLElement) => { | |
element.tabIndex = -1; | |
element.setAttribute('aria-hidden', 'true'); | |
}; | |
const submitButton = createInput(); | |
const shadowDOM = true; | |
let realForm: HTMLFormElement; | |
submitButton.type = SUBMIT; | |
username.proxy = username.input = createInput(); | |
password.proxy = password.input = createInput(); | |
proxyForm.appendChild(username.proxy); | |
proxyForm.appendChild(password.proxy); | |
proxyForm.appendChild(submitButton); | |
proxyForm.method = 'post'; | |
proxyForm.style.cssText = 'visibility: hidden; height: 0; width: 0'; | |
proxyForm.addEventListener(SUBMIT, (e) => { | |
e.preventDefault(); | |
}); | |
hide(username.proxy); | |
hide(password.proxy); | |
hide(submitButton); | |
hide(proxyForm); | |
export const attachProxyForm = (hostElement: HTMLElement): void => { | |
if (shadowDOM) { | |
hostElement.appendChild(proxyForm); | |
} | |
}; | |
export const storePassword = (): void => { | |
submitButton.click(); | |
}; | |
const sync = (from: HTMLInputElement, to: HTMLInputElement) => { | |
const listener = () => { | |
const fromValue = from.value; | |
if (to.value !== fromValue) { | |
to.value = fromValue; | |
} | |
}; | |
const fromValue = from.value; | |
if (!to.value && fromValue) { | |
to.value = fromValue; | |
} | |
from.addEventListener(INPUT, listener); | |
return listener; | |
}; | |
const synchronise = (field: InputWrapper) => { | |
const { input, proxy } = field; | |
if (input && proxy) { | |
field.proxyListener = sync(proxy, input); | |
field.inputListener = sync(input, proxy); | |
} | |
}; | |
const connect = (field: InputWrapper, newInput: HTMLInputElement) => { | |
if (shadowDOM) { | |
const { | |
input, inputListener, proxy, proxyListener, | |
} = field; | |
if (input && inputListener && proxy && proxyListener) { | |
input.removeEventListener(INPUT, inputListener); | |
proxy.removeEventListener(INPUT, proxyListener); | |
} | |
const { id, type } = (field.input = newInput); | |
Object.assign(proxy, { id, type }); | |
synchronise(field); | |
} | |
}; | |
export const connectUsername = (input: HTMLInputElement): void => { | |
connect( | |
username, | |
input | |
); | |
}; | |
export const connectPassword = (input: HTMLInputElement): void => { | |
connect( | |
password, | |
input | |
); | |
if (realForm) { | |
realForm.removeEventListener(SUBMIT, storePassword); | |
} | |
if (input.form) { | |
realForm = input.form; | |
if (realForm) { | |
realForm.addEventListener(SUBMIT, storePassword); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment