Make WordPress Core

Ticket #42888: 42888-4.diff

File 42888-4.diff, 18.7 KB (added by Iceable, 7 years ago)

New approach for all password fields + accessbiility

  • src/wp-admin/css/login.css

    diff --git src/wp-admin/css/login.css src/wp-admin/css/login.css
    index 5da174cadc..002b931922 100644
    p { 
    7474}
    7575
    7676.login .password-input-wrapper {
    77     display: table;
     77        display: table;
     78        margin: 2px 0 16px 0;
    7879}
    7980
    8081.login .input.password-input {
    p { 
    8788}
    8889
    8990.login .button.button-secondary {
    90     display: table-cell;
    91     border-radius: 0;
    92     vertical-align: middle;
     91        display: table-cell;
     92        border-radius: 0;
     93        box-shadow: none;
     94        height: 100%;
     95        vertical-align: middle;
     96}
     97
     98.login .wp-hide-pw-wrap {
     99        display: table-cell;
     100        vertical-align: middle;
     101        height: 28px;
     102}
     103
     104.no-js .hide-if-no-js{
     105        display: none;
    93106}
    94107
    95108.login form {
    p { 
    220233
    221234.login #pass-strength-result {
    222235        font-weight: 600;
    223         margin: -1px 5px 16px 0;
     236        margin: -17px 5px 16px 0;
    224237        padding: 6px 5px;
    225238        text-align: center;
    226239        width: 100%;
  • src/wp-admin/js/user-profile.js

    diff --git src/wp-admin/js/user-profile.js src/wp-admin/js/user-profile.js
    index e95a42844e..adb1ba7d36 100644
     
    55                $pass1Row,
    66                $pass1Wrap,
    77                $pass1,
    8                 $pass1Text,
    9                 $pass1Label,
    108                $pass2,
    119                $weakRow,
    1210                $weakCheckbox,
     
    4442                }
    4543
    4644                if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) {
    47                         $pass1Wrap.addClass( 'show-password' );
     45                        $pass1.attr( 'type', 'text' );
    4846                } else {
    4947                        $toggleButton.trigger( 'click' );
    5048                }
     
    5856
    5957                $pass1Wrap = $pass1.parent();
    6058
    61                 $pass1Text = $( '<input type="text"/>' )
    62                         .attr( {
    63                                 'id':           'pass1-text',
    64                                 'name':         'pass1-text',
    65                                 'autocomplete': 'off'
    66                         } )
    67                         .addClass( $pass1[0].className )
    68                         .data( 'pw', $pass1.data( 'pw' ) )
    69                         .val( $pass1.val() )
    70                         .on( inputEvent, function () {
    71                                 if ( $pass1Text.val() === currentPass ) {
    72                                         return;
    73                                 }
    74                                 $pass2.val( $pass1Text.val() );
    75                                 $pass1.val( $pass1Text.val() ).trigger( 'pwupdate' );
    76                                 currentPass = $pass1Text.val();
    77                         } );
    78 
    79                 $pass1.after( $pass1Text );
    80 
    8159                if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) {
    8260                        generatePassword();
    8361                }
     
    8866                        }
    8967
    9068                        currentPass = $pass1.val();
    91                         if ( $pass1Text.val() !== currentPass ) {
    92                                 $pass1Text.val( currentPass );
    93                         }
    94                         $pass1.add( $pass1Text ).removeClass( 'short bad good strong' );
     69
     70                        $pass1.removeClass( 'short bad good strong' );
    9571                        showOrHideWeakPasswordCheckbox();
    9672                } );
    9773        }
    9874
    99         function resetToggle() {
    100                 $toggleButton
    101                         .data( 'toggle', 0 )
    102                         .attr({
    103                                 'aria-label': userProfileL10n.ariaHide
    104                         })
    105                         .find( '.text' )
    106                                 .text( userProfileL10n.hide )
    107                         .end()
    108                         .find( '.dashicons' )
    109                                 .removeClass( 'dashicons-visibility' )
    110                                 .addClass( 'dashicons-hidden' );
    111 
    112                 $pass1Text.focus();
    113 
    114                 $pass1Label.attr( 'for', 'pass1-text' );
    115         }
    116 
    11775        function bindToggleButton() {
    11876                $toggleButton = $pass1Row.find('.wp-hide-pw');
    11977                $toggleButton.show().on( 'click', function () {
    120                         if ( 1 === parseInt( $toggleButton.data( 'toggle' ), 10 ) ) {
    121                                 $pass1Wrap.addClass( 'show-password' );
    122 
    123                                 resetToggle();
    124 
    125                                 if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
    126                                         $pass1Text[0].setSelectionRange( 0, 100 );
    127                                 }
     78                        if ( 'password' === $pass1.attr( 'type' ) ) {
     79                                $pass1.attr( 'type', 'text' );
     80                                $toggleButton
     81                                        .attr({
     82                                                'aria-label': userProfileL10n.ariaHide
     83                                        })
     84                                        .find( '.text' )
     85                                                .text( userProfileL10n.hide )
     86                                        .end()
     87                                        .find( '.dashicons' )
     88                                                .removeClass( 'dashicons-visibility' )
     89                                                .addClass( 'dashicons-hidden' );
    12890                        } else {
    129                                 $pass1Wrap.removeClass( 'show-password' );
     91                                $pass1.attr( 'type', 'password' );
    13092                                $toggleButton
    131                                         .data( 'toggle', 1 )
    13293                                        .attr({
    13394                                                'aria-label': userProfileL10n.ariaShow
    13495                                        })
     
    139100                                                .removeClass('dashicons-hidden')
    140101                                                .addClass('dashicons-visibility');
    141102
    142                                 $pass1.focus();
    143 
    144                                 $pass1Label.attr( 'for', 'pass1' );
    145 
    146103                                if ( ! _.isUndefined( $pass1[0].setSelectionRange ) ) {
    147104                                        $pass1[0].setSelectionRange( 0, 100 );
    148105                                }
    149106                        }
     107                        $pass1.focus();
    150108                });
    151109        }
    152110
     
    155113                        $generateButton,
    156114                        $cancelButton;
    157115
    158                 $pass1Row = $('.user-pass1-wrap');
    159                 $pass1Label = $pass1Row.find('th label').attr( 'for', 'pass1-text' );
     116                $pass1Row = $('.user-pass1-wrap, .user-pass-wrap');
    160117
    161118                // hide this
    162119                $('.user-pass2-wrap').hide();
     
    176133                $pass1 = $('#pass1');
    177134                if ( $pass1.length ) {
    178135                        bindPass1();
     136                } else {
     137                        // Password field for the login form
     138                        $pass1 = $('#user_pass');
    179139                }
    180140
    181141                /**
     
    197157                if ( $pass1.is( ':hidden' ) ) {
    198158                        $pass1.prop( 'disabled', true );
    199159                        $pass2.prop( 'disabled', true );
    200                         $pass1Text.prop( 'disabled', true );
    201160                }
    202161
    203162                $passwordWrapper = $pass1Row.find( '.wp-pwd' );
     
    219178                        // Enable the inputs when showing.
    220179                        $pass1.attr( 'disabled', false );
    221180                        $pass2.attr( 'disabled', false );
    222                         $pass1Text.attr( 'disabled', false );
    223 
    224                         if ( $pass1Text.val().length === 0 ) {
    225                                 generatePassword();
    226                         }
    227181
    228                         _.defer( function() {
    229                                 $pass1Text.focus();
    230                                 if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
    231                                         $pass1Text[0].setSelectionRange( 0, 100 );
    232                                 }
    233                         }, 0 );
    234182                } );
    235183
    236184                $cancelButton = $pass1Row.find( 'button.wp-cancel-pw' );
    237185                $cancelButton.on( 'click', function () {
    238186                        updateLock = false;
    239187
    240                         // Clear any entered password.
    241                         $pass1Text.val( '' );
    242 
    243188                        // Generate a new password.
    244189                        wp.ajax.post( 'generate-password' )
    245190                                .done( function( data ) {
     
    256201                        // Disable the inputs when hiding to prevent autofill and submission.
    257202                        $pass1.prop( 'disabled', true );
    258203                        $pass2.prop( 'disabled', true );
    259                         $pass1Text.prop( 'disabled', true );
    260204
    261205                        resetToggle();
    262206
     
    273217                        $pass1.prop( 'disabled', false );
    274218                        $pass2.prop( 'disabled', false );
    275219                        $pass2.val( $pass1.val() );
    276                         $pass1Wrap.removeClass( 'show-password' );
    277220                });
    278221        }
    279222
     
    313256                var passStrength = $('#pass-strength-result')[0];
    314257
    315258                if ( passStrength.className ) {
    316                         $pass1.add( $pass1Text ).addClass( passStrength.className );
     259                        $pass1.addClass( passStrength.className );
    317260                        if ( $( passStrength ).is( '.short, .bad' ) ) {
    318261                                if ( ! $weakCheckbox.prop( 'checked' ) ) {
    319262                                        $submitButtons.prop( 'disabled', true );
  • src/wp-login.php

    diff --git src/wp-login.php src/wp-login.php
    index 6415b1544a..4174851c56 100644
    function login_header( $title = 'Log In', $message = '', $wp_error = '' ) { 
    175175
    176176        ?>
    177177        </head>
    178         <body class="login <?php echo esc_attr( implode( ' ', $classes ) ); ?>">
     178        <body class="login no-js <?php echo esc_attr( implode( ' ', $classes ) ); ?>">
     179        <script type="text/javascript">
     180                document.body.className = document.body.className.replace('no-js','js');
     181        </script>
    179182        <?php
    180183        /**
    181184         * Fires in the login page header after the body tag is opened.
    switch ( $action ) { 
    601604        ?>
    602605
    603606        <form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">
    604         <p>
    605                 <label for="user_login" ><?php _e( 'Username or Email Address' ); ?><br />
    606                 <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" /></label>
    607         </p>
     607        <div>
     608                <label for="user_login" ><?php _e( 'Username or Email Address' ); ?></label>
     609                <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" />
     610        </div>
    608611        <?php
    609612        /**
    610613         * Fires inside the lostpassword form tags, before the hidden fields.
    switch ( $action ) { 
    614617        do_action( 'lostpassword_form' );
    615618        ?>
    616619                <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
    617                 <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" /></p>
     620                <div class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" /></div>
    618621        </form>
    619622
    620         <p id="nav">
    621         <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
    622         <?php
    623         if ( get_option( 'users_can_register' ) ) :
    624                 $registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
     623        <div id="nav">
     624                <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
     625                <?php
     626                if ( get_option( 'users_can_register' ) ) :
     627                        $registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
    625628
    626                 echo esc_html( $login_link_separator );
     629                        echo esc_html( $login_link_separator );
    627630
    628                 /** This filter is documented in wp-includes/general-template.php */
    629                 echo apply_filters( 'register', $registration_url );
    630         endif;
    631         ?>
    632         </p>
     631                        /** This filter is documented in wp-includes/general-template.php */
     632                        echo apply_filters( 'register', $registration_url );
     633                endif;
     634                ?>
     635        </div>
    633636
    634637        <?php
    635638        login_footer( 'user_login' );
    switch ( $action ) { 
    705708        <input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" />
    706709
    707710        <div class="user-pass1-wrap">
    708                 <p>
    709                         <label for="pass1"><?php _e( 'New password' ); ?></label>
    710                 </p>
     711
     712                <label for="pass1"><?php _e( 'New password' ); ?></label>
    711713
    712714                <div class="wp-pwd">
    713715                        <div class="password-input-wrapper">
    714716                                <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" />
    715                                 <span class="button button-secondary wp-hide-pw hide-if-no-js">
    716                                         <span class="dashicons dashicons-hidden"></span>
    717                                 </span>
     717
     718                                <div class="wp-hide-pw-wrap hide-if-no-js">
     719                                        <button type="button" class="button button-secondary wp-hide-pw" data-toggle="0" aria-label="<?php esc_attr_e( 'Hide password' ); ?>">
     720                                                <span class="dashicons dashicons-hidden"></span>
     721                                                <span class="text"><?php _e( 'Hide' ); ?></span>
     722                                        </button>
     723                                </div>
     724
    718725                        </div>
    719726                        <div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator' ); ?></div>
    720727                </div>
    switch ( $action ) { 
    726733                </div>
    727734        </div>
    728735
    729         <p class="user-pass2-wrap">
    730                 <label for="pass2"><?php _e( 'Confirm new password' ); ?></label><br />
     736        <div class="user-pass2-wrap">
     737                <label for="pass2"><?php _e( 'Confirm new password' ); ?></label>
    731738                <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
    732         </p>
     739        </div>
    733740
    734741        <p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p>
    735742        <br class="clear" />
    switch ( $action ) { 
    745752        do_action( 'resetpass_form', $user );
    746753        ?>
    747754        <input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" />
    748         <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Reset Password' ); ?>" /></p>
     755        <div class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Reset Password' ); ?>" /></div>
    749756        </form>
    750757
    751         <p id="nav">
    752         <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
    753         <?php
    754         if ( get_option( 'users_can_register' ) ) :
    755                 $registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
     758        <div id="nav">
     759                <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
     760                <?php
     761                if ( get_option( 'users_can_register' ) ) :
     762                        $registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
    756763
    757                 echo esc_html( $login_link_separator );
     764                        echo esc_html( $login_link_separator );
    758765
    759                 /** This filter is documented in wp-includes/general-template.php */
    760                 echo apply_filters( 'register', $registration_url );
    761         endif;
    762         ?>
    763         </p>
     766                        /** This filter is documented in wp-includes/general-template.php */
     767                        echo apply_filters( 'register', $registration_url );
     768                endif;
     769                ?>
     770        </div>
    764771
    765772        <?php
    766773        login_footer( 'user_pass' );
    switch ( $action ) { 
    821828                login_header( __( 'Registration Form' ), '<p class="message register">' . __( 'Register For This Site' ) . '</p>', $errors );
    822829        ?>
    823830        <form name="registerform" id="registerform" action="<?php echo esc_url( site_url( 'wp-login.php?action=register', 'login_post' ) ); ?>" method="post" novalidate="novalidate">
    824         <p>
    825                 <label for="user_login"><?php _e( 'Username' ); ?><br />
    826                 <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>
    827         </p>
    828         <p>
    829                 <label for="user_email"><?php _e( 'Email' ); ?><br />
    830                 <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( wp_unslash( $user_email ) ); ?>" size="25" /></label>
    831         </p>
     831        <div>
     832                <label for="user_login"><?php _e( 'Username' ); ?></label>
     833                <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( wp_unslash( $user_login ) ); ?>" size="20" autocapitalize="off" />
     834        </div>
     835        <div>
     836                <label for="user_email"><?php _e( 'Email' ); ?></label>
     837                <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( wp_unslash( $user_email ) ); ?>" size="25" />
     838        </div>
    832839        <?php
    833840        /**
    834841         * Fires following the 'Email' field in the user registration form.
    switch ( $action ) { 
    840847        <p id="reg_passmail"><?php _e( 'Registration confirmation will be emailed to you.' ); ?></p>
    841848        <br class="clear" />
    842849        <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
    843         <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" /></p>
     850        <div class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" /></div>
    844851        </form>
    845852
    846         <p id="nav">
    847         <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
    848         <?php echo esc_html( $login_link_separator ); ?>
    849         <a href="<?php echo esc_url( wp_lostpassword_url() ); ?>"><?php _e( 'Lost your password?' ); ?></a>
    850         </p>
     853        <div id="nav">
     854                <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
     855                <?php echo esc_html( $login_link_separator ); ?>
     856                <a href="<?php echo esc_url( wp_lostpassword_url() ); ?>"><?php _e( 'Lost your password?' ); ?></a>
     857        </div>
    851858
    852859        <?php
    853860        login_footer( 'user_login' );
    switch ( $action ) { 
    10201027                } else {
    10211028                        $aria_describedby_error = '';
    10221029                }
     1030
     1031                wp_enqueue_script( 'user-profile' );
    10231032        ?>
    10241033
    10251034        <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post">
    1026         <p>
    1027                 <label for="user_login"><?php _e( 'Username or Email Address' ); ?><br />
    1028                 <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>
    1029         </p>
    1030         <p>
    1031                 <label for="user_pass"><?php _e( 'Password' ); ?><br />
    1032                 <input type="password" name="pwd" id="user_pass"<?php echo $aria_describedby_error; ?> class="input" value="" size="20" /></label>
    1033         </p>
     1035        <div>
     1036                <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label>
     1037                <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" />
     1038        </div>
     1039        <div class="user-pass-wrap">
     1040                <label for="user_pass"><?php _e( 'Password' ); ?></label>
     1041                <div class="wp-pwd">
     1042                        <div class="password-input-wrapper">
     1043                                <input type="password" name="pwd" id="user_pass"<?php echo $aria_describedby_error; ?> class="input password-input" value="" size="20" />
     1044                                <div class="wp-hide-pw-wrap hide-if-no-js" style="
     1045                                ">
     1046                                        <button type="button" class="button button-secondary wp-hide-pw" data-toggle="0" aria-label="<?php esc_attr_e( 'Show password' ); ?>">
     1047                                                <span class="dashicons dashicons-visibility"></span>
     1048                                                <span class="text"><?php _e( 'Show' ); ?></span>
     1049                                        </button>
     1050                                </div>
     1051
     1052                        </div>
     1053                </div>
     1054
     1055        </div>
     1056
    10341057        <?php
    10351058        /**
    10361059         * Fires following the 'Password' field in the login form.
    switch ( $action ) { 
    10391062         */
    10401063        do_action( 'login_form' );
    10411064        ?>
    1042         <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>
    1043         <p class="submit">
     1065        <div class="forgetmenot"><label for="rememberme"><input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked( $rememberme ); ?> /> <?php esc_html_e( 'Remember Me' ); ?></label></div>
     1066        <div class="submit">
    10441067                <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Log In' ); ?>" />
    10451068        <?php   if ( $interim_login ) { ?>
    10461069                <input type="hidden" name="interim-login" value="1" />
    switch ( $action ) { 
    10511074                <input type="hidden" name="customize-login" value="1" />
    10521075        <?php endif; ?>
    10531076                <input type="hidden" name="testcookie" value="1" />
    1054         </p>
     1077        </div>
    10551078        </form>
    10561079
    10571080        <?php if ( ! $interim_login ) { ?>
    1058         <p id="nav">
    1059         <?php
    1060         if ( ! isset( $_GET['checkemail'] ) || ! in_array( $_GET['checkemail'], array( 'confirm', 'newpass' ) ) ) :
    1061                 if ( get_option( 'users_can_register' ) ) :
    1062                         $registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
     1081        <div id="nav">
     1082                <?php
     1083                if ( ! isset( $_GET['checkemail'] ) || ! in_array( $_GET['checkemail'], array( 'confirm', 'newpass' ) ) ) :
     1084                        if ( get_option( 'users_can_register' ) ) :
     1085                                $registration_url = sprintf( '<a href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
    10631086
    1064                         /** This filter is documented in wp-includes/general-template.php */
    1065                         echo apply_filters( 'register', $registration_url );
     1087                                /** This filter is documented in wp-includes/general-template.php */
     1088                                echo apply_filters( 'register', $registration_url );
    10661089
    1067                         echo esc_html( $login_link_separator );
    1068                 endif;
    1069                 ?>
    1070                 <a href="<?php echo esc_url( wp_lostpassword_url() ); ?>"><?php _e( 'Lost your password?' ); ?></a>
    1071         <?php endif; ?>
    1072         </p>
     1090                                echo esc_html( $login_link_separator );
     1091                        endif;
     1092                        ?>
     1093                        <a href="<?php echo esc_url( wp_lostpassword_url() ); ?>"><?php _e( 'Lost your password?' ); ?></a>
     1094                <?php endif; ?>
     1095        </div>
    10731096        <?php } ?>
    10741097
    10751098        <script type="text/javascript">