WordPress.org

Make WordPress Core

Changeset 46256


Ignore:
Timestamp:
09/23/2019 06:05:16 PM (3 months ago)
Author:
afercia
Message:

Login and Registration: Add a "Show password" button on the login page.

The ability for users to see the password they're typing improves usability and accessibility of the login users flow.

  • brings the login screen in line with the same feature already used in the New User, Edit User, and Reset Password pages
  • improves association of labels and input fields by using explicit association with for / id attributes
  • slightly increases the "Remember me" label font size

Props johnbillion, Iceable, audrasjb, joyously, adamsilverstein, boemedia, DrewAPicture, shadyvb, birgire, peterwilsoncc, pento, anevins, davidbaumwald, whyisjake, afercia.
Fixes #42888.

Location:
trunk/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/admin/user-profile.js

    r46103 r46256  
    88
    99        $pass1Row,
    10         $pass1Wrap,
    1110        $pass1,
    12         $pass1Text,
    13         $pass1Label,
    1411        $pass2,
    1512        $weakRow,
     
    3734
    3835        if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) {
    39             $pass1Wrap.addClass( 'show-password' );
     36            $pass1.attr( 'type', 'text' );
    4037        } else {
    4138            $toggleButton.trigger( 'click' );
     
    4845    function bindPass1() {
    4946        currentPass = $pass1.val();
    50 
    51         $pass1Wrap = $pass1.parent();
    52 
    53         $pass1Text = $( '<input type="text"/>' )
    54             .attr( {
    55                 'id':           'pass1-text',
    56                 'name':         'pass1-text',
    57                 'autocomplete': 'off'
    58             } )
    59             .addClass( $pass1[0].className )
    60             .data( 'pw', $pass1.data( 'pw' ) )
    61             .val( $pass1.val() )
    62             .on( 'input', function () {
    63                 if ( $pass1Text.val() === currentPass ) {
    64                     return;
    65                 }
    66                 $pass2.val( $pass1Text.val() );
    67                 $pass1.val( $pass1Text.val() ).trigger( 'pwupdate' );
    68                 currentPass = $pass1Text.val();
    69             } );
    70 
    71         $pass1.after( $pass1Text );
    7247
    7348        if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) {
     
    8156
    8257            currentPass = $pass1.val();
    83             if ( $pass1Text.val() !== currentPass ) {
    84                 $pass1Text.val( currentPass );
    85             }
    86             $pass1.add( $pass1Text ).removeClass( 'short bad good strong' );
     58
     59            $pass1.removeClass( 'short bad good strong' );
    8760            showOrHideWeakPasswordCheckbox();
    8861        } );
    8962    }
    9063
    91     function resetToggle() {
     64    function resetToggle( show ) {
    9265        $toggleButton
    93             .data( 'toggle', 0 )
    9466            .attr({
    95                 'aria-label': userProfileL10n.ariaHide
     67                'aria-label': show ? userProfileL10n.ariaShow : userProfileL10n.ariaHide
    9668            })
    9769            .find( '.text' )
    98                 .text( userProfileL10n.hide )
     70                .text( show ? userProfileL10n.show : userProfileL10n.hide )
    9971            .end()
    10072            .find( '.dashicons' )
    101                 .removeClass( 'dashicons-visibility' )
    102                 .addClass( 'dashicons-hidden' );
    103 
    104         $pass1Text.focus();
    105 
    106         $pass1Label.attr( 'for', 'pass1-text' );
     73                .removeClass( show ? 'dashicons-hidden' : 'dashicons-visibility' )
     74                .addClass( show ? 'dashicons-visibility' : 'dashicons-hidden' );
    10775    }
    10876
     
    11078        $toggleButton = $pass1Row.find('.wp-hide-pw');
    11179        $toggleButton.show().on( 'click', function () {
    112             if ( 1 === parseInt( $toggleButton.data( 'toggle' ), 10 ) ) {
    113                 $pass1Wrap.addClass( 'show-password' );
    114 
    115                 resetToggle();
    116 
    117                 if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
    118                     $pass1Text[0].setSelectionRange( 0, 100 );
    119                 }
     80            if ( 'password' === $pass1.attr( 'type' ) ) {
     81                $pass1.attr( 'type', 'text' );
     82                resetToggle( false );
    12083            } else {
    121                 $pass1Wrap.removeClass( 'show-password' );
    122                 $toggleButton
    123                     .data( 'toggle', 1 )
    124                     .attr({
    125                         'aria-label': userProfileL10n.ariaShow
    126                     })
    127                     .find( '.text' )
    128                         .text( userProfileL10n.show )
    129                     .end()
    130                     .find( '.dashicons' )
    131                         .removeClass('dashicons-hidden')
    132                         .addClass('dashicons-visibility');
    133 
    134                 $pass1.focus();
    135 
    136                 $pass1Label.attr( 'for', 'pass1' );
    137 
    138                 if ( ! _.isUndefined( $pass1[0].setSelectionRange ) ) {
    139                     $pass1[0].setSelectionRange( 0, 100 );
    140                 }
     84                $pass1.attr( 'type', 'password' );
     85                resetToggle( true );
     86            }
     87
     88            $pass1.focus();
     89
     90            if ( ! _.isUndefined( $pass1[0].setSelectionRange ) ) {
     91                $pass1[0].setSelectionRange( 0, 100 );
    14192            }
    14293        });
     
    14899            $cancelButton;
    149100
    150         $pass1Row = $('.user-pass1-wrap');
    151         $pass1Label = $pass1Row.find('th label').attr( 'for', 'pass1-text' );
    152 
    153         // hide this
     101        $pass1Row = $( '.user-pass1-wrap, .user-pass-wrap' );
     102
     103        // Hide the confirm password field when JavaScript support is enabled.
    154104        $('.user-pass2-wrap').hide();
    155105
     
    169119        if ( $pass1.length ) {
    170120            bindPass1();
     121        } else {
     122            // Password field for the login form.
     123            $pass1 = $( '#user_pass' );
    171124        }
    172125
     
    190143            $pass1.prop( 'disabled', true );
    191144            $pass2.prop( 'disabled', true );
    192             $pass1Text.prop( 'disabled', true );
    193145        }
    194146
     
    212164            $pass1.attr( 'disabled', false );
    213165            $pass2.attr( 'disabled', false );
    214             $pass1Text.attr( 'disabled', false );
    215 
    216             if ( $pass1Text.val().length === 0 ) {
     166
     167            if ( $pass1.val().length === 0 ) {
    217168                generatePassword();
    218169            }
    219 
    220             _.defer( function() {
    221                 $pass1Text.focus();
    222                 if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
    223                     $pass1Text[0].setSelectionRange( 0, 100 );
    224                 }
    225             }, 0 );
    226170        } );
    227171
     
    231175
    232176            // Clear any entered password.
    233             $pass1Text.val( '' );
     177            $pass1.val( '' );
    234178
    235179            // Generate a new password.
     
    249193            $pass1.prop( 'disabled', true );
    250194            $pass2.prop( 'disabled', true );
    251             $pass1Text.prop( 'disabled', true );
    252 
    253             resetToggle();
     195
     196            resetToggle( false );
    254197
    255198            if ( $pass1Row.closest( 'form' ).is( '#your-profile' ) ) {
     
    266209            $pass2.prop( 'disabled', false );
    267210            $pass2.val( $pass1.val() );
    268             $pass1Wrap.removeClass( 'show-password' );
    269211        });
    270212    }
     
    306248
    307249        if ( passStrength.className ) {
    308             $pass1.add( $pass1Text ).addClass( passStrength.className );
     250            $pass1.addClass( passStrength.className );
    309251            if ( $( passStrength ).is( '.short, .bad' ) ) {
    310252                if ( ! $weakCheckbox.prop( 'checked' ) ) {
  • trunk/src/wp-admin/css/forms.css

    r46248 r46256  
    15011501    }
    15021502
    1503     .wp-pwd [type="text"],
    1504     .wp-pwd [type="password"] {
    1505         padding-right: 88px;
     1503    /* Needs higher specificity than normal input type text and password. */
     1504    #profile-page .form-table #pass1 {
     1505        padding-right: 90px;
    15061506    }
    15071507
  • trunk/src/wp-admin/css/install.css

    r45673 r46256  
    302302    }
    303303
     304    .wp-pwd #pass1 {
     305        padding-right: 50px;
     306    }
     307
     308    .wp-pwd .button.wp-hide-pw {
     309        right: 0;
     310    }
     311
     312    #pass-strength-result {
     313        width: 100%;
     314    }
    304315}
    305316
  • trunk/src/wp-admin/css/login.css

    r46203 r46256  
    3636        0 0 0 1px #5b9dd9,
    3737        0 0 2px 1px rgba(30, 140, 190, 0.8);
    38 }
    39 
    40 .ie8 a:focus {
    41     outline: #5b9dd9 solid 1px;
    4238}
    4339
     
    7672}
    7773
    78 .login .password-input-wrapper {
    79     position: relative;
    80 }
    81 
    82 .login .input.password-input {
    83     margin: 0;
    84 }
    85 
    8674.login .input::-ms-clear {
    8775    display: none;
     
    9280}
    9381
    94 .login .button.button-secondary {
     82.login .button.wp-hide-pw {
    9583    background: transparent;
    9684    border: 1px solid transparent;
     
    10391    position: absolute;
    10492    right: 0;
    105     top: 0;
    106 }
    107 
    108 .login .button.button-secondary:hover {
     93    top: 3px;
     94}
     95
     96.login .button.wp-hide-pw:hover {
    10997    background: transparent;
    11098}
    11199
    112 .login .button.button-secondary:focus {
     100.login .button.wp-hide-pw:focus {
    113101    background: transparent;
    114102    border-color: #5b9dd9;
     
    116104}
    117105
    118 .login .button.button-secondary:active {
     106.login .button.wp-hide-pw:active {
    119107    background: transparent;
    120108    box-shadow: none;
    121109    transform: none;
     110}
     111
     112.login .button.wp-hide-pw .dashicons {
     113    top: 4px;
     114}
     115
     116.login .wp-pwd {
     117    position: relative;
     118}
     119
     120.no-js .hide-if-no-js {
     121    display: none;
    122122}
    123123
     
    196196}
    197197
    198 .login form .forgetmenot label {
    199     font-size: 12px;
    200     line-height: 1.58333333;
     198.login .forgetmenot label,
     199.login .pw-weak label {
     200    line-height: 1.5;
     201    vertical-align: baseline;
    201202}
    202203
     
    271272
    272273.login form .input,
    273 .login input[type="text"] {
     274.login input[type="text"],
     275.login input[type="password"] {
    274276    font-size: 24px;
    275277    width: 100%;
    276278    padding: 5px;
    277     margin: 2px 6px 16px 0;
    278 }
    279 
    280 .login-action-rp form .input,
    281 .login-action-rp input[type="text"] {
    282     padding: 5px 45px 5px 5px;
     279    margin: 3px 6px 16px 0;
     280}
     281
     282.js.login input.password-input,
     283.js.login-action-rp form .input,
     284.js.login-action-rp input[type="text"] {
     285    padding-right: 45px;
    283286}
    284287
     
    289292}
    290293
    291 .ie7 .login form .input,
    292 .ie8 .login form .input {
    293     font-family: sans-serif;
    294 }
    295 
    296 .login-action-rp input[type="text"] {
    297     box-shadow: none;
    298     margin: 0;
     294.js.login-action-rp input[type="text"],
     295.js.login-action-rp input[type="password"] {
     296    margin-bottom: 0;
    299297}
    300298
  • trunk/src/wp-login.php

    r46229 r46256  
    826826
    827827        <form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">
    828             <p>
    829                 <label for="user_login" ><?php _e( 'Username or Email Address' ); ?><br />
    830                 <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" /></label>
    831             </p>
     828
     829            <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label>
     830            <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" />
    832831            <?php
    833832
     
    841840            ?>
    842841            <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
    843             <p class="submit">
     842            <div class="submit">
    844843                <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" />
    845             </p>
     844            </div>
    846845        </form>
    847846
    848         <p id="nav">
     847        <div id="nav">
    849848            <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
    850849            <?php
     
    860859
    861860            ?>
    862         </p>
     861        </div>
    863862        <?php
    864863
     
    937936
    938937            <div class="user-pass1-wrap">
    939                 <p>
    940                     <label for="pass1"><?php _e( 'New password' ); ?></label>
    941                 </p>
     938
     939                <label for="pass1"><?php _e( 'New password' ); ?></label>
    942940
    943941                <div class="wp-pwd">
    944                     <div class="password-input-wrapper">
    945                         <input type="password" data-reveal="1" data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" name="pass1" id="pass1" class="input password-input" size="24" value="" autocomplete="off" aria-describedby="pass-strength-result" />
    946                         <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js">
    947                             <span class="dashicons dashicons-hidden" aria-hidden="true"></span>
    948                         </button>
    949                     </div>
     942                    <input type="password" data-reveal="1" data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" name="pass1" id="pass1" class="input password-input" size="24" value="" autocomplete="off" aria-describedby="pass-strength-result" />
     943
     944                    <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Hide password' ); ?>">
     945                        <span class="dashicons dashicons-hidden" aria-hidden="true"></span>
     946                    </button>
    950947                    <div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator' ); ?></div>
    951948                </div>
    952949                <div class="pw-weak">
    953                     <label>
    954                         <input type="checkbox" name="pw_weak" class="pw-checkbox" />
    955                         <?php _e( 'Confirm use of weak password' ); ?>
    956                     </label>
     950                    <input type="checkbox" name="pw_weak" id="pw-weak" class="pw-checkbox" />
     951                    <label for="pw-weak"><?php _e( 'Confirm use of weak password' ); ?></label>
    957952                </div>
    958953            </div>
    959954
    960             <p class="user-pass2-wrap">
    961                 <label for="pass2"><?php _e( 'Confirm new password' ); ?></label><br />
     955            <div class="user-pass2-wrap">
     956                <label for="pass2"><?php _e( 'Confirm new password' ); ?></label>
    962957                <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
    963             </p>
     958            </div>
    964959
    965960            <p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p>
     
    979974            ?>
    980975            <input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" />
    981             <p class="submit">
     976            <div class="submit">
    982977                <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Reset Password' ); ?>" />
    983             </p>
     978            </div>
    984979        </form>
    985980
    986         <p id="nav">
     981        <div id="nav">
    987982            <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
    988983            <?php
     
    998993
    999994            ?>
    1000         </p>
     995        </div>
    1001996        <?php
    1002997
     
    10581053        ?>
    10591054        <form name="registerform" id="registerform" action="<?php echo esc_url( site_url( 'wp-login.php?action=register', 'login_post' ) ); ?>" method="post" novalidate="novalidate">
    1060             <p>
    1061                 <label for="user_login"><?php _e( 'Username' ); ?><br />
    1062                 <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( wp_unslash( $user_login ) ); ?>" size="20" autocapitalize="off" /></label>
    1063             </p>
    1064             <p>
    1065                 <label for="user_email"><?php _e( 'Email' ); ?><br />
    1066                 <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( wp_unslash( $user_email ) ); ?>" size="25" /></label>
    1067             </p>
     1055            <div>
     1056                <label for="user_login"><?php _e( 'Username' ); ?></label>
     1057                <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( wp_unslash( $user_login ) ); ?>" size="20" autocapitalize="off" />
     1058            </div>
     1059            <div>
     1060                <label for="user_email"><?php _e( 'Email' ); ?></label>
     1061                <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( wp_unslash( $user_email ) ); ?>" size="25" />
     1062            </div>
    10681063            <?php
    10691064
     
    10811076            <br class="clear" />
    10821077            <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
    1083             <p class="submit">
     1078            <div class="submit">
    10841079                <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" />
    1085             </p>
     1080            </div>
    10861081        </form>
    10871082
    1088         <p id="nav">
     1083        <div id="nav">
    10891084            <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
    10901085                <?php echo esc_html( $login_link_separator ); ?>
    10911086            <a href="<?php echo esc_url( wp_lostpassword_url() ); ?>"><?php _e( 'Lost your password?' ); ?></a>
    1092         </p>
     1087        </div>
    10931088        <?php
    10941089
     
    13301325        }
    13311326
     1327        wp_enqueue_script( 'user-profile' );
    13321328        ?>
    13331329
    13341330        <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post">
    1335             <p>
    1336                 <label for="user_login"><?php _e( 'Username or Email Address' ); ?><br />
    1337                 <input type="text" name="log" id="user_login"<?php echo $aria_describedby_error; ?> class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" /></label>
    1338             </p>
    1339             <p>
    1340                 <label for="user_pass"><?php _e( 'Password' ); ?><br />
    1341                 <input type="password" name="pwd" id="user_pass"<?php echo $aria_describedby_error; ?> class="input" value="" size="20" /></label>
    1342             </p>
     1331            <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label>
     1332            <input type="text" name="log" id="user_login"<?php echo $aria_describedby_error; ?> class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" />
     1333
     1334            <div class="user-pass-wrap">
     1335                <label for="user_pass"><?php _e( 'Password' ); ?></label>
     1336                <div class="wp-pwd">
     1337                    <input type="password" name="pwd" id="user_pass"<?php echo $aria_describedby_error; ?> class="input password-input" value="" size="20" />
     1338                    <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Show password' ); ?>">
     1339                        <span class="dashicons dashicons-visibility" aria-hidden="true"></span>
     1340                    </button>
     1341                </div>
     1342            </div>
    13431343            <?php
    13441344
     
    13511351
    13521352            ?>
    1353             <p class="forgetmenot"><label for="rememberme"><input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked( $rememberme ); ?> /> <?php esc_html_e( 'Remember Me' ); ?></label></p>
    1354             <p class="submit">
     1353            <div class="forgetmenot"><input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked( $rememberme ); ?> /> <label for="rememberme"><?php esc_html_e( 'Remember Me' ); ?></label></div>
     1354            <div class="submit">
    13551355                <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Log In' ); ?>" />
    13561356                <?php
     
    13741374                ?>
    13751375                <input type="hidden" name="testcookie" value="1" />
    1376             </p>
     1376            </div>
    13771377        </form>
    13781378
     
    13811381        if ( ! $interim_login ) {
    13821382            ?>
    1383             <p id="nav">
     1383            <div id="nav">
    13841384                <?php
    13851385
     
    14001400
    14011401                ?>
    1402             </p>
     1402            </div>
    14031403            <?php
    14041404        }
Note: See TracChangeset for help on using the changeset viewer.