From 89169b64ff75ffa6ff13099c58976e8f4df5a8a0 Mon Sep 17 00:00:00 2001 From: Miguel Cabrerizo <30386061+doncicuto@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:24:36 +0100 Subject: [PATCH] fix: detect autofill in chrome to enable login buttons (#7056) * fix: detect autofill in chrome to enable login buttons * fix: add -webkit-autofill to input scss --------- Co-authored-by: Max Peintner --- .../static/resources/scripts/form_submit.js | 111 +++++++++++------- .../themes/scss/styles/input/input_base.scss | 57 +++++---- 2 files changed, 106 insertions(+), 62 deletions(-) diff --git a/internal/api/ui/login/static/resources/scripts/form_submit.js b/internal/api/ui/login/static/resources/scripts/form_submit.js index b822c4c35b..e51d5dad45 100644 --- a/internal/api/ui/login/static/resources/scripts/form_submit.js +++ b/internal/api/ui/login/static/resources/scripts/form_submit.js @@ -1,58 +1,87 @@ -function disableSubmit(checks, button) { - let form = document.getElementsByTagName('form')[0]; - let inputs = form.getElementsByTagName('input'); - if (button) { - button.disabled = true; - } - addRequiredEventListener(inputs, checks, form, button); - disableDoubleSubmit(form, button); +// if an autofilled input is deleted we remove the attribute +function detectDelete(event) { + const key = event.key; + if (key === "Backspace" || key === "Delete") { + event.target.isAutofilled = false; + } +} +// if the autofill associated animation is detected we add a property +// and check if submit button should be disabled or not +function autofill(target, checks, form, inputs, button) { + if (!target.isAutofilled) { + target.isAutofilled = true; + target.dispatchEvent(new CustomEvent("autofill", { bubbles: true })); toggleButton(checks, form, inputs, button); + } +} + +function disableSubmit(checks, button) { + let form = document.getElementsByTagName("form")[0]; + let inputs = form.getElementsByTagName("input"); + if (button) { + button.disabled = true; + } + addRequiredEventListener(inputs, checks, form, button); + disableDoubleSubmit(form, button); + + toggleButton(checks, form, inputs, button); } function addRequiredEventListener(inputs, checks, form, button) { - let eventType = 'input'; - for (i = 0; i < inputs.length; i++) { - if (inputs[i].required) { - eventType = 'input'; - if (inputs[i].type === 'checkbox') { - eventType = 'click'; - } - inputs[i].addEventListener(eventType, function () { - toggleButton(checks, form, inputs, button); - }); - } + let eventType = "input"; + for (i = 0; i < inputs.length; i++) { + if (inputs[i].required) { + eventType = "input"; + if (inputs[i].type === "checkbox") { + eventType = "click"; + } + + inputs[i].addEventListener(eventType, function () { + toggleButton(checks, form, inputs, button); + }); + + if (inputs[i].type !== "checkbox") { + // hack for Chrome, add an animationstart event listener + // if input is autofilled: https://gist.github.com/jonathantneal/d462fc2bf761a10c9fca60eb634f6977?permalink_comment_id=2901919 + inputs[i].addEventListener("animationstart", (event) => + autofill(event.target, checks, form, inputs, button) + ); + + inputs[i].addEventListener("keydown", detectDelete); + } } + } } function disableDoubleSubmit(form, button) { - form.addEventListener('submit', function () { - document.body.classList.add('waiting'); - button.disabled = true; - }); + form.addEventListener("submit", function () { + document.body.classList.add("waiting"); + button.disabled = true; + }); } function toggleButton(checks, form, inputs, button) { - if (checks !== undefined) { - if (checks() === false) { - button.disabled = true; - return; - } + if (checks !== undefined) { + if (checks() === false) { + button.disabled = true; + return; } - const targetValue = !allRequiredDone(form, inputs); - button.disabled = targetValue; + } + const targetValue = !allRequiredDone(form, inputs); + button.disabled = targetValue; } function allRequiredDone(form, inputs) { - for (i = 0; i < inputs.length; i++) { - if (inputs[i].required) { - if (inputs[i].type === 'checkbox' && !inputs[i].checked) { - return false; - } - if (inputs[i].value === '') { - return false; - } - } + for (i = 0; i < inputs.length; i++) { + if (inputs[i].required) { + if (inputs[i].type === "checkbox" && !inputs[i].checked) { + return false; + } + if (inputs[i].value === "" && !inputs[i].isAutofilled) { + return false; + } } - return true; -} \ No newline at end of file + } + return true; +} diff --git a/internal/api/ui/login/static/resources/themes/scss/styles/input/input_base.scss b/internal/api/ui/login/static/resources/themes/scss/styles/input/input_base.scss index 02cd12e8ed..69204a05c0 100644 --- a/internal/api/ui/login/static/resources/themes/scss/styles/input/input_base.scss +++ b/internal/api/ui/login/static/resources/themes/scss/styles/input/input_base.scss @@ -7,26 +7,41 @@ $lgn-input-border-width: 1px !default; $lgn-input-placeholder-font-size: 14px !default; @mixin lgn-input-base { - display: block; - box-sizing: border-box; - padding-inline-start: $lgn-input-padding-start; - outline: none; - display: inline-block; - text-align: start; - cursor: text; - border-radius: $lgn-input-border-radius; - transform: all .2 linear; - font-size: 1rem; - border-style: solid; - border-width: $lgn-input-border-width; - height: $lgn-input-line-height; - padding: $lgn-input-padding; - transition: border-color .2s ease-in-out; - width: 100%; - margin: $lgn-input-margin; + display: block; + box-sizing: border-box; + padding-inline-start: $lgn-input-padding-start; + outline: none; + display: inline-block; + text-align: start; + cursor: text; + border-radius: $lgn-input-border-radius; + transform: all 0.2 linear; + font-size: 1rem; + border-style: solid; + border-width: $lgn-input-border-width; + height: $lgn-input-line-height; + padding: $lgn-input-padding; + transition: border-color 0.2s ease-in-out; + width: 100%; + margin: $lgn-input-margin; - &::placeholder { - font-size: $lgn-input-placeholder-font-size; - font-style: italic; - } + &::placeholder { + font-size: $lgn-input-placeholder-font-size; + font-style: italic; + } + + &:autofill { + animation-duration: 50000s; + animation-name: onautofillstart; + } + + &:-webkit-autofill { + animation-duration: 50000s; + animation-name: onautofillstart; + } +} + +@keyframes onautofillstart { + from { + } }