Skip to content

Commit 1dff73d

Browse files
committed
Login and Registration: Add Caps Lock notice to password input.
Add a notification when typing passwords on the user registration, user login, and user profile screens that notifies the user if they are typing with caps lock enabled. This can help reduce user friction when logging in, prevent user error when creating passwords, and reduce the need for a user to use the show password button. Props dartiss, swissspidy, johnbillion, nikunj8866, pmbaldha, mosescursor, sirlouen, westonruter, praful2111, devsabbirahmed, kawsar007, najmulsaju, yashyadav247, sajjad67, joedolson. Fixes #48345. git-svn-id: https://develop.svn.wordpress.org/trunk@60988 602fd350-edb4-49c9-b593-d223f7449a82
1 parent c62fe7e commit 1dff73d

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed

src/js/_enqueues/admin/user-profile.js

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
$form,
2121
originalFormContent,
2222
$passwordWrapper,
23-
successTimeout;
23+
successTimeout,
24+
isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false,
25+
ua = navigator.userAgent.toLowerCase(),
26+
isSafari = window.safari !== 'undefined' && typeof window.safari === 'object',
27+
isFirefox = ua.indexOf( 'firefox' ) !== -1;
2428

2529
function generatePassword() {
2630
if ( typeof zxcvbn !== 'function' ) {
@@ -80,6 +84,8 @@
8084
$pass1.removeClass( 'short bad good strong' );
8185
showOrHideWeakPasswordCheckbox();
8286
} );
87+
88+
bindCapsLockWarning( $pass1 );
8389
}
8490

8591
function resetToggle( show ) {
@@ -213,6 +219,8 @@
213219
} else {
214220
// Password field for the login form.
215221
$pass1 = $( '#user_pass' );
222+
223+
bindCapsLockWarning( $pass1 );
216224
}
217225

218226
/*
@@ -332,6 +340,79 @@
332340
}
333341
}
334342

343+
/**
344+
* Bind Caps Lock detection to a password input field.
345+
*
346+
* @param {jQuery} $input The password input field.
347+
*/
348+
function bindCapsLockWarning( $input ) {
349+
var $capsWarning,
350+
$capsIcon,
351+
$capsText,
352+
capsLockOn = false;
353+
354+
// Skip warning on macOS Safari + Firefox (they show native indicators).
355+
if ( isMac && ( isSafari || isFirefox ) ) {
356+
return;
357+
}
358+
359+
$capsWarning = $( '<div id="caps-warning" class="caps-warning"></div>' );
360+
$capsIcon = $( '<span class="caps-icon" aria-hidden="true"><svg viewBox="0 0 24 26" xmlns="http://www.w3.org/2000/svg" fill="#3c434a" stroke="#3c434a" stroke-width="0.5"><path d="M12 5L19 15H16V19H8V15H5L12 5Z"/><rect x="8" y="21" width="8" height="1.5" rx="0.75"/></svg></span>' );
361+
$capsText = $( '<span>', { 'class': 'caps-warning-text', text: __( 'Caps lock is on.' ) } );
362+
$capsWarning.append( $capsIcon, $capsText );
363+
364+
$input.parent( 'div' ).append( $capsWarning );
365+
366+
$input.on( 'keydown', function( jqEvent ) {
367+
var event = jqEvent.originalEvent;
368+
369+
// Skip if key is not a printable character.
370+
// Key length > 1 usually means non-printable (e.g., "Enter", "Tab").
371+
if ( event.ctrlKey || event.metaKey || event.altKey || ! event.key || event.key.length !== 1 ) {
372+
return;
373+
}
374+
375+
var state = isCapsLockOn( event );
376+
377+
// React when the state changes or if caps lock is on when the user starts typing.
378+
if ( state !== capsLockOn ) {
379+
capsLockOn = state;
380+
381+
if ( capsLockOn ) {
382+
$capsWarning.show();
383+
// Don't duplicate existing screen reader Caps lock notifications.
384+
if ( event.key !== 'CapsLock' ) {
385+
wp.a11y.speak( __( 'Caps lock is on.' ), 'assertive' );
386+
}
387+
} else {
388+
$capsWarning.hide();
389+
}
390+
}
391+
} );
392+
393+
$input.on( 'blur', function() {
394+
if ( ! document.hasFocus() ) {
395+
return;
396+
}
397+
capsLockOn = false;
398+
$capsWarning.hide();
399+
} );
400+
}
401+
402+
/**
403+
* Determines if Caps Lock is currently enabled.
404+
*
405+
* On macOS Safari and Firefox, the native warning is preferred,
406+
* so this function returns false to suppress custom warnings.
407+
*
408+
* @param {KeyboardEvent} e The keydown event object.
409+
*
410+
* @return {boolean} True if Caps Lock is on, false otherwise.
411+
*/
412+
function isCapsLockOn( event ) {
413+
return event.getModifierState( 'CapsLock' );
414+
}
415+
335416
function showOrHideWeakPasswordCheckbox() {
336417
var passStrengthResult = $('#pass-strength-result');
337418

src/wp-admin/css/forms.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,37 @@ fieldset label,
713713
display: inline-block;
714714
}
715715

716+
/* Caps lock warning */
717+
.wp-pwd .caps-warning {
718+
display: none;
719+
position: relative;
720+
background: #fcf9e8;
721+
border: 1px solid #f0c33c;
722+
color: #1d2327;
723+
padding: 6px 10px;
724+
top: -8px;
725+
}
726+
727+
.profile-php .wp-pwd .caps-warning {
728+
padding: 3px 5px;
729+
top: -4px;
730+
border-radius: 4px;
731+
}
732+
733+
.wp-pwd .caps-icon {
734+
display: inline-flex;
735+
justify-content: center;
736+
width: 20px;
737+
height: 20px;
738+
margin-right: 5px;
739+
vertical-align: middle;
740+
}
741+
742+
.wp-pwd .caps-warning-text {
743+
vertical-align: middle;
744+
}
745+
/* Caps lock warning */
746+
716747
p.search-box {
717748
display: flex;
718749
flex-wrap: wrap;
@@ -1640,6 +1671,10 @@ table.form-table td .updated p {
16401671
padding: 8px;
16411672
}
16421673

1674+
.profile-php .wp-pwd .caps-warning {
1675+
padding: 8px;
1676+
}
1677+
16431678
.password-input-wrapper {
16441679
display: block;
16451680
}

0 commit comments

Comments
 (0)