Refine UI for FTP modal and shiny updates

Numerous changes to make the FTP modal experience a good one.  These include:
 * Update HTML used by both the form here and the form on the standalone screen
 * Allow users to cancel FTP install
 * Focus locking in the modal
 * Focus on modal form on load
 * ARIA Attributes
 * Style Enhancements
 * Add low screen height (such as phone and some tablets) friendly experience for entering credentials

Props ericlewis, afercia 
Fixes #31608



git-svn-id: https://develop.svn.wordpress.org/trunk@31949 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Aaron Jorbin 2015-04-01 02:47:55 +00:00
parent 235b83b4c0
commit 9932d7973d
4 changed files with 227 additions and 58 deletions

View File

@ -864,11 +864,58 @@ table.form-table td .updated p {
margin: 25px;
}
.request-filesystem-credentials-dialog-content input[type="text"],
.request-filesystem-credentials-dialog-content input[type="password"] {
width: 85%;
.request-filesystem-credentials-form input[type="text"],
.request-filesystem-credentials-form input[type="password"] {
display: block;
}
.request-filesystem-credentials-dialog input[type="text"],
.request-filesystem-credentials-dialog input[type="password"] {
width: 100%;
}
.request-filesystem-credentials-form .field-title {
font-weight: 600;
}
.request-filesystem-credentials-dialog label[for="hostname"],
.request-filesystem-credentials-dialog label[for="public_key"],
.request-filesystem-credentials-dialog label[for="private_key"] {
display: block;
margin-bottom: 1em;
}
.request-filesystem-credentials-dialog .ftp-username,
.request-filesystem-credentials-dialog .ftp-password {
float: left;
width: 48%;
}
.request-filesystem-credentials-dialog .ftp-password {
margin-left: 4%;
}
.request-filesystem-credentials-dialog .request-filesystem-credentials-action-buttons {
text-align: right;
}
.request-filesystem-credentials-dialog label[for="ftp"] {
margin-right: 10px;
}
#request-filesystem-credentials-dialog .button:not(:last-child) {
margin-right: 10px;
}
#request-filesystem-credentials-form .cancel-button {
display: none;
}
#request-filesystem-credentials-dialog .cancel-button {
display: inline;
}
/* =Media Queries
-------------------------------------------------------------- */
@ -1098,6 +1145,20 @@ table.form-table td .updated p {
max-width: 400px;
width: auto;
}
}
@media only screen and (max-height: 480px) {
/* Request Credentials */
.request-filesystem-credentials-dialog .notification-dialog{
width: 100%;
height: 100%;
position: fixed;
top: 0;
margin: 0;
left: 0;
overflow-y: auto;
}
}
/* Smartphone */

View File

@ -1125,9 +1125,9 @@ jQuery(function($){
-->
</script>
<form action="<?php echo esc_url( $form_post ) ?>" method="post">
<div>
<h3><?php _e('Connection Information') ?></h3>
<p><?php
<div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form">
<h3 id="request-filesystem-credentials-title"><?php _e( 'Connection Information' ) ?></h3>
<p id="request-filesystem-credentials-desc"><?php
$label_user = __('Username');
$label_pass = __('Password');
_e('To perform the requested action, WordPress needs to access your web server.');
@ -1146,39 +1146,36 @@ jQuery(function($){
}
_e('If you do not remember your credentials, you should contact your web host.');
?></p>
<table class="form-table">
<tr>
<th scope="row"><label for="hostname"><?php _e('Hostname') ?></label></th>
<td><input name="hostname" type="text" id="hostname" value="<?php echo esc_attr($hostname); if ( !empty($port) ) echo ":$port"; ?>"<?php disabled( defined('FTP_HOST') ); ?> size="40" /></td>
</tr>
<tr>
<th scope="row"><label for="username"><?php echo $label_user; ?></label></th>
<td><input name="username" type="text" id="username" value="<?php echo esc_attr($username) ?>"<?php disabled( defined('FTP_USER') ); ?> size="40" /></td>
</tr>
<tr>
<th scope="row"><label for="password"><?php echo $label_pass; ?></label></th>
<td><div><input name="password" type="password" id="password" value="<?php if ( defined('FTP_PASS') ) echo '*****'; ?>"<?php disabled( defined('FTP_PASS') ); ?> size="40" /></div>
<div><em><?php if ( ! defined('FTP_PASS') ) _e( 'This password will not be stored on the server.' ); ?></em></div></td>
</tr>
<label for="hostname">
<span class="field-title"><?php _e( 'Hostname' ) ?></span>
<input name="hostname" type="text" id="hostname" aria-describedby="request-filesystem-credentials-desc" class="code" placeholder="<?php esc_attr_e( __( 'example: www.mysite.com' ) ) ?>" value="<?php echo esc_attr($hostname); if ( !empty($port) ) echo ":$port"; ?>"<?php disabled( defined('FTP_HOST') ); ?> />
</label>
<div class="ftp-username">
<label for="username">
<span class="field-title"><?php echo $label_user; ?></span>
<input name="username" type="text" id="username" value="<?php echo esc_attr($username) ?>"<?php disabled( defined('FTP_USER') ); ?> />
</label>
</div>
<div class="ftp-password">
<label for="password">
<span class="field-title"><?php echo $label_pass; ?></span>
<input name="password" type="password" id="password" value="<?php if ( defined('FTP_PASS') ) echo '*****'; ?>"<?php disabled( defined('FTP_PASS') ); ?> />
<em><?php if ( ! defined('FTP_PASS') ) _e( 'This password will not be stored on the server.' ); ?></em>
</label>
</div>
<?php if ( isset($types['ssh']) ) : ?>
<tr id="ssh_keys" style="<?php if ( 'ssh' != $connection_type ) echo 'display:none' ?>">
<th scope="row"><?php _e('Authentication Keys') ?>
<div class="key-labels textright">
<label for="public_key"><?php _e('Public Key:') ?></label ><br />
<label for="private_key"><?php _e('Private Key:') ?></label>
</div></th>
<td><br /><input name="public_key" type="text" id="public_key" value="<?php echo esc_attr($public_key) ?>"<?php disabled( defined('FTP_PUBKEY') ); ?> size="40" />
<br /><input name="private_key" type="text" id="private_key" value="<?php echo esc_attr($private_key) ?>"<?php disabled( defined('FTP_PRIKEY') ); ?> size="40" />
<div><?php _e('Enter the location on the server where the keys are located. If a passphrase is needed, enter that in the password field above.') ?></div></td>
</tr>
<h4><?php _e('Authentication Keys') ?></h4>
<label for="public_key">
<span class="field-title"><?php _e('Public Key:') ?></span>
<input name="public_key" type="text" id="public_key" aria-describedby="auth-keys-desc" value="<?php echo esc_attr($public_key) ?>"<?php disabled( defined('FTP_PUBKEY') ); ?> />
</label>
<label for="private_key">
<span class="field-title"><?php _e('Private Key:') ?></span>
<input name="private_key" type="text" id="private_key" value="<?php echo esc_attr($private_key) ?>"<?php disabled( defined('FTP_PRIKEY') ); ?> />
</label>
<span id="auth-keys-desc"><?php _e('Enter the location on the server where the public and private keys are located. If a passphrase is needed, enter that in the password field above.') ?></span>
<?php endif; ?>
<tr>
<th scope="row"><?php _e('Connection Type') ?></th>
<td>
<h4><?php _e('Connection Type') ?></h4>
<fieldset><legend class="screen-reader-text"><span><?php _e('Connection Type') ?></span></legend>
<?php
$disabled = disabled( (defined('FTP_SSL') && FTP_SSL) || (defined('FTP_SSH') && FTP_SSH), true, false );
@ -1189,17 +1186,16 @@ jQuery(function($){
</label>
<?php endforeach; ?>
</fieldset>
</td>
</tr>
</table>
<?php
foreach ( (array) $extra_fields as $field ) {
if ( isset( $_POST[ $field ] ) )
echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( wp_unslash( $_POST[ $field ] ) ) . '" />';
}
submit_button( __( 'Proceed' ), 'button', 'upgrade' );
?>
<p class="request-filesystem-credentials-action-buttons">
<button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button>
<?php submit_button( __( 'Proceed' ), 'button', 'upgrade', false ); ?>
</p>
</div>
</form>
<?php
@ -1223,7 +1219,7 @@ function wp_print_request_filesystem_credentials_modal() {
?>
<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
<div class="notification-dialog-background"></div>
<div class="notification-dialog">
<div class="notification-dialog" role="dialog" aria-labelledby="request-filesystem-credentials-title" tabindex="0">
<div class="request-filesystem-credentials-dialog-content">
<?php request_filesystem_credentials( site_url() ); ?>
<div>

View File

@ -78,6 +78,15 @@ window.wp = window.wp || {};
*/
wp.updates.updateQueue = [];
/**
* Store a jQuery reference to return focus to when exiting the request credentials modal.
*
* @since 4.2.0
*
* @var jQuery object
*/
wp.updates.$elToReturnFocusToFromCredentialsModal = null;
/**
* Decrement update counts throughout the various menus.
*
@ -144,6 +153,10 @@ window.wp = window.wp || {};
}
$message.addClass( 'updating-message' );
if ( $message.html() !== wp.updates.l10n.updating ){
$message.data( 'originaltext', $message.html() );
}
$message.text( wp.updates.l10n.updating );
wp.a11y.speak( wp.updates.l10n.updatingMsg );
@ -247,12 +260,12 @@ window.wp = window.wp || {};
* @since 4.2.0
*/
wp.updates.showErrorInCredentialsForm = function( message ) {
var $notificationDialog = $( '.notification-dialog' );
var $modal = $( '.notification-dialog' );
// Remove any existing error
$notificationDialog.find( '.error' ).remove();
// Remove any existing error.
$modal.find( '.error' ).remove();
$notificationDialog.find( 'h3' ).after( '<div class="error">' + message + '</div>' );
$modal.find( 'h3' ).after( '<div class="error">' + message + '</div>' );
};
/**
@ -291,18 +304,105 @@ window.wp = window.wp || {};
/**
* Request the users filesystem credentials if we don't have them already
* Request the users filesystem credentials if we don't have them already.
*
* @since 4.2.0
*/
wp.updates.requestFilesystemCredentials = function() {
wp.updates.requestFilesystemCredentials = function( event ) {
if ( wp.updates.updateDoneSuccessfully === false ) {
/*
* For the plugin install screen, return the focus to the install button
* after exiting the credentials request modal.
*/
if ( 'plugin-install' === pagenow && event ) {
wp.updates.$elToReturnFocusToFromCredentialsModal = $( event.target );
}
wp.updates.updateLock = true;
$( 'body' ).addClass( 'modal-open' );
$( '#request-filesystem-credentials-dialog' ).show();
wp.updates.requestForCredentialsModalOpen();
}
};
/**
* Keydown handler for the request for credentials modal.
*
* Close the modal when the escape key is pressed.
* Constrain keyboard navigation to inside the modal.
*
* @since 4.2.0
*/
wp.updates.keydown = function( event ) {
if ( 27 === event.keyCode ) {
wp.updates.requestForCredentialsModalCancel();
} else if ( 9 === event.keyCode ) {
// #upgrade button must always be the last focusable element in the dialog.
if ( event.target.id === 'upgrade' && ! event.shiftKey ) {
$( '#hostname' ).focus();
event.preventDefault();
} else if ( event.target.id === 'hostname' && event.shiftKey ) {
$( '#upgrade' ).focus();
event.preventDefault();
}
}
};
/**
* Open the request for credentials modal.
*
* @since 4.2.0
*/
wp.updates.requestForCredentialsModalOpen = function() {
var $modal = $( '#request-filesystem-credentials-dialog' );
$( 'body' ).addClass( 'modal-open' );
$modal.show();
$modal.find( '#hostname' ).focus();
$modal.keydown( wp.updates.keydown );
};
/**
* Close the request for credentials modal.
*
* @since 4.2.0
*/
wp.updates.requestForCredentialsModalClose = function() {
$( '#request-filesystem-credentials-dialog' ).hide();
$( 'body' ).removeClass( 'modal-open' );
wp.updates.$elToReturnFocusToFromCredentialsModal.focus();
};
/**
* The steps that need to happen when the modal is canceled out
*
* @since 4.2.0
*/
wp.updates.requestForCredentialsModalCancel = function() {
// no updateLock and no updateQueue means we already have cleared things up
var slug, $message;
if( wp.updates.updateLock === false && wp.updates.updateQueue.length === 0 ){
return;
}
slug = wp.updates.updateQueue[0].data.slug,
// remove the lock, and clear the queue
wp.updates.updateLock = false;
wp.updates.updateQueue = [];
wp.updates.requestForCredentialsModalClose();
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
$message = $( '[data-slug="' + slug + '"]' ).next().find( '.update-message' );
} else if ( 'plugin-install' === pagenow ) {
$message = $( '.plugin-card-' + slug ).find( '.update-now' );
}
$message.removeClass( 'updating-message' );
$message.html( $message.data( 'originaltext' ) );
wp.a11y.speak( wp.updates.l10n.updateCancel );
};
$( document ).ready( function() {
/*
* Check whether a user needs to submit filesystem credentials based on whether
@ -322,8 +422,7 @@ window.wp = window.wp || {};
wp.updates.filesystemCredentials.ssh.publicKey = $('#public_key').val();
wp.updates.filesystemCredentials.ssh.privateKey = $('#private_key').val();
$( '#request-filesystem-credentials-dialog' ).hide();
$( 'body' ).removeClass( 'modal-open' );
wp.updates.requestForCredentialsModalClose();
// Unlock and invoke the queue.
wp.updates.updateLock = false;
@ -332,14 +431,21 @@ window.wp = window.wp || {};
return false;
});
// Close the request credentials modal when
$( '#request-filesystem-credentials-dialog [data-js-action="close"], .notification-dialog-background' ).on( 'click', function() {
wp.updates.requestForCredentialsModalCancel();
});
// Click handler for plugin updates in List Table view.
$( '.plugin-update-tr .update-link' ).on( 'click', function( e ) {
$( '.plugin-update-tr' ).on( 'click', '.update-link', function( e ) {
e.preventDefault();
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.updateLock ) {
wp.updates.requestFilesystemCredentials();
wp.updates.requestFilesystemCredentials( e );
}
var $row = $( e.target ).parents( '.plugin-update-tr' );
wp.updates.updatePlugin( $row.data( 'plugin' ), $row.data( 'slug' ) );
var updateRow = $( e.target ).parents( '.plugin-update-tr' );
// Return the user to the input box of the plugin's table row after closing the modal.
wp.updates.$elToReturnFocusToFromCredentialsModal = $( '#' + updateRow.data( 'slug' ) ).find( '.check-column input' );
wp.updates.updatePlugin( updateRow.data( 'plugin' ), updateRow.data( 'slug' ) );
} );
$( '#bulk-action-form' ).on( 'submit', function( e ) {
@ -360,9 +466,14 @@ window.wp = window.wp || {};
}
} );
$( '.plugin-card .update-now' ).on( 'click', function( e ) {
$( '.plugin-card' ).on( 'click', '.update-now', function( e ) {
e.preventDefault();
var $button = $( e.target );
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.updateLock ) {
wp.updates.requestFilesystemCredentials( e );
}
wp.updates.updatePlugin( $button.data( 'plugin' ), $button.data( 'slug' ) );
} );

View File

@ -529,6 +529,7 @@ function wp_default_scripts( &$scripts ) {
'updateFailed' => __( 'Update failed.' ),
'updatingMsg' => __( 'Updating... please wait.' ),
'updatedMsg' => __( 'Update completed successfully.' ),
'updateCancel' => __( 'Update canceled' ),
)
) );