简体   繁体   中英

How to detect when user first starts typing text into password field, without being triggered by browser autofills/autocompletes

I've looked through similar questions on stack, but have not found the answer I am looking for.

I have a password field with a button that toggles visibility of the password, so the user can ensure no typoes if desired. However, I do not want this button to be used to view people's saved passwords by other people who may have access to the same computer.

So my solution was, to not enable this visibility toggle button until the user has typed something into the password field. I cannot figure out how to do this however, since any event I use to figure out when the user starts typing, is also being used by the browser when it autofills/autocompletes. I've tried the change, input, and keyup events, and each of them seems to be fired by the browser automatically as soon as the field becomes visible and it autofills a saved password. Using Chrome for testing at the moment.

html:

            <div class="input-group">
                <input type="password" class="form-control needs-validation" id="sign-up-password" name="sign_up_password" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" required>
                <button type="button" class="btn btn-secondary password-visibility-toggle" disabled>
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
                        <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
                        <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
                    </svg>
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye-slash d-none" viewBox="0 0 16 16">
                        <path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7.028 7.028 0 0 0-2.79.588l.77.771A5.944 5.944 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.134 13.134 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755-.165.165-.337.328-.517.486l.708.709z"/>
                        <path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829l.822.822zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829z"/>
                        <path d="M3.35 5.47c-.18.16-.353.322-.518.487A13.134 13.134 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7.029 7.029 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709zm10.296 8.884-12-12 .708-.708 12 12-.708.708z"/>
                    </svg>
                </button>
            </div>

javascript

// password visibility toggles
document.querySelectorAll( '.password-visibility-toggle' ).forEach( ( passwordVisibilityButton ) => {
    const inputGroup = passwordVisibilityButton.closest( '.input-group' );
    const passwordInput = inputGroup.querySelector( 'input' );
    passwordInput.addEventListener( 'change', ( event ) => {
        console.log( 'test' );
        if ( passwordVisibilityButton.disabled ) {
            passwordVisibilityButton.disabled = false;
            passwordVisibilityButton.addEventListener( 'click', ( event ) => {
                if ( passwordInput.getAttribute( 'type' ) == 'password' ) {
                    passwordInput.type = 'text';
                    inputGroup.querySelector( '.bi-eye' ).classList.add( 'd-none' );
                    inputGroup.querySelector( '.bi-eye-slash' ).classList.remove( 'd-none' );
                } else {
                    passwordInput.type = 'password';
                    inputGroup.querySelector( '.bi-eye' ).classList.remove( 'd-none' );
                    inputGroup.querySelector( '.bi-eye-slash' ).classList.add( 'd-none' );
                }
            } );
        }
    } );
} );

This code just triggers before the user inputs anything and enables the toggle button. Any ideas or advice to fix appreciated. Also using bootstrap 5.2 if that matters.

It seems that behavior of input type="password" is totally under the browser control nowadays. Thankfully, the input type="text" is still libre and we can use it as we please. Thus, instead of fighting with that, we can create our own password field, albeit without password manager feature which anyway is not what we actually want on a communal computer. So, here it is:

 const toggleMap = {show: 'hide', hide: 'show'}; const group = document.querySelector( '.input-group' ); const password = group.querySelector( '#sign-up-password' ); const passmask = group.querySelector( '#sign-up-passmask' ); const toggle = group.querySelector( '.password-visibility-toggle' ); toggle.addEventListener( 'click', () => { group.dataset.toggle = toggleMap[group.dataset.toggle]; }); password.addEventListener( 'input', event => { const value = event.target.value; passmask.value = value.replace(/./g, '*'); if (toggle.disabled =.value.length) group.dataset;toggle = 'hide'; });
 .input { position: relative; }.input > input { font-family: monospace; } #sign-up-password, #sign-up-password::selection { background: transparent; caret-color: black; } #sign-up-password::selection { background: #F236; } #sign-up-passmask { position: absolute; display: flex; z-index: -1; top: 0; border-color: transparent; }.input-group[data-toggle='hide'] >.password-visibility-toggle >.bi-eye, .input-group[data-toggle='show'] >.password-visibility-toggle >.bi-eye-slash { display: none; }.input-group[data-toggle='hide'] #sign-up-password, .input-group[data-toggle='show'] #sign-up-passmask { color: transparent; }
 <div class="input-group" data-toggle="hide"> <span class="input"> <input type="text" class="form-control needs-validation" id="sign-up-password" name="sign_up_password" pattern="(?=.*\d)(?=.*[az])(?=.*[AZ]).{8,}" required> <input type="text" id="sign-up-passmask"> </span> <button type="button" class="btn btn-secondary password-visibility-toggle" disabled> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16"> <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/> <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/> </svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye-slash d-none" viewBox="0 0 16 16"> <path d="M13.359 11.238C15.06 9.72 16 8 16 8s-3-5.5-8-5.5a7.028 7.028 0 0 0-2.79.588l.77.771A5.944 5.944 0 0 1 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.134 13.134 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755-.165.165-.337.328-.517.486l.708.709z"/> <path d="M11.297 9.176a3.5 3.5 0 0 0-4.474-4.474l.823.823a2.5 2.5 0 0 1 2.829 2.829l.822.822zm-2.943 1.299.822.822a3.5 3.5 0 0 1-4.474-4.474l.823.823a2.5 2.5 0 0 0 2.829 2.829z"/> <path d="M3.35 5.47c-.18.16-.353.322-.518.487A13.134 13.134 0 0 0 1.172 8l.195.288c.335.48.83 1.12 1.465 1.755C4.121 11.332 5.881 12.5 8 12.5c.716 0 1.39-.133 2.02-.36l.77.772A7.029 7.029 0 0 1 8 13.5C3 13.5 0 8 0 8s.939-1.721 2.641-3.238l.708.709zm10.296 8.884-12-12.708-.708 12 12-.708.708z"/> </svg> </button> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM