wp/wp-admin/js/user-profile.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /* global ajaxurl, pwsL10n */
     1 /* global ajaxurl, pwsL10n, userProfileL10n */
     2 (function($){
     2 (function($) {
       
     3 	var updateLock = false,
       
     4 
       
     5 		$pass1Row,
       
     6 		$pass1Wrap,
       
     7 		$pass1,
       
     8 		$pass1Text,
       
     9 		$pass1Label,
       
    10 		$pass2,
       
    11 		$weakRow,
       
    12 		$weakCheckbox,
       
    13 		$toggleButton,
       
    14 		$submitButtons,
       
    15 		$submitButton,
       
    16 		currentPass,
       
    17 		inputEvent;
       
    18 
       
    19 	/*
       
    20 	 * Use feature detection to determine whether password inputs should use
       
    21 	 * the `keyup` or `input` event. Input is preferred but lacks support
       
    22 	 * in legacy browsers.
       
    23 	 */
       
    24 	if ( 'oninput' in document.createElement( 'input' ) ) {
       
    25 		inputEvent = 'input';
       
    26 	} else {
       
    27 		inputEvent = 'keyup';
       
    28 	}
       
    29 
       
    30 	function generatePassword() {
       
    31 		if ( typeof zxcvbn !== 'function' ) {
       
    32 			setTimeout( generatePassword, 50 );
       
    33 			return;
       
    34 		} else if ( ! $pass1.val() ) {
       
    35 			// zxcvbn loaded before user entered password.
       
    36 			$pass1.val( $pass1.data( 'pw' ) );
       
    37 			$pass1.trigger( 'pwupdate' );
       
    38 			showOrHideWeakPasswordCheckbox();
       
    39 		}
       
    40 		else {
       
    41 			// zxcvbn loaded after the user entered password, check strength.
       
    42 			check_pass_strength();
       
    43 			showOrHideWeakPasswordCheckbox();
       
    44 		}
       
    45 
       
    46 		if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) {
       
    47 			$pass1Wrap.addClass( 'show-password' );
       
    48 		} else {
       
    49 			$toggleButton.trigger( 'click' );
       
    50 		}
       
    51 
       
    52 		// Once zxcvbn loads, passwords strength is known.
       
    53 		$( '#pw-weak-text-label' ).html( userProfileL10n.warnWeak );
       
    54 	}
       
    55 
       
    56 	function bindPass1() {
       
    57 		currentPass = $pass1.val();
       
    58 
       
    59 		$pass1Wrap = $pass1.parent();
       
    60 
       
    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 
       
    81 		if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) {
       
    82 			generatePassword();
       
    83 		}
       
    84 
       
    85 		$pass1.on( inputEvent + ' pwupdate', function () {
       
    86 			if ( $pass1.val() === currentPass ) {
       
    87 				return;
       
    88 			}
       
    89 
       
    90 			currentPass = $pass1.val();
       
    91 			if ( $pass1Text.val() !== currentPass ) {
       
    92 				$pass1Text.val( currentPass );
       
    93 			}
       
    94 			$pass1.add( $pass1Text ).removeClass( 'short bad good strong' );
       
    95 			showOrHideWeakPasswordCheckbox();
       
    96 		} );
       
    97 	}
       
    98 
       
    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 
       
   117 	function bindToggleButton() {
       
   118 		$toggleButton = $pass1Row.find('.wp-hide-pw');
       
   119 		$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 				}
       
   128 			} else {
       
   129 				$pass1Wrap.removeClass( 'show-password' );
       
   130 				$toggleButton
       
   131 					.data( 'toggle', 1 )
       
   132 					.attr({
       
   133 						'aria-label': userProfileL10n.ariaShow
       
   134 					})
       
   135 					.find( '.text' )
       
   136 						.text( userProfileL10n.show )
       
   137 					.end()
       
   138 					.find( '.dashicons' )
       
   139 						.removeClass('dashicons-hidden')
       
   140 						.addClass('dashicons-visibility');
       
   141 
       
   142 				$pass1.focus();
       
   143 
       
   144 				$pass1Label.attr( 'for', 'pass1' );
       
   145 
       
   146 				if ( ! _.isUndefined( $pass1[0].setSelectionRange ) ) {
       
   147 					$pass1[0].setSelectionRange( 0, 100 );
       
   148 				}
       
   149 			}
       
   150 		});
       
   151 	}
       
   152 
       
   153 	function bindPasswordForm() {
       
   154 		var $passwordWrapper,
       
   155 			$generateButton,
       
   156 			$cancelButton;
       
   157 
       
   158 		$pass1Row = $('.user-pass1-wrap');
       
   159 		$pass1Label = $pass1Row.find('th label').attr( 'for', 'pass1-text' );
       
   160 
       
   161 		// hide this
       
   162 		$('.user-pass2-wrap').hide();
       
   163 
       
   164 		$submitButton = $( '#submit, #wp-submit' ).on( 'click', function () {
       
   165 			updateLock = false;
       
   166 		});
       
   167 
       
   168 		$submitButtons = $submitButton.add( ' #createusersub' );
       
   169 
       
   170 		$weakRow = $( '.pw-weak' );
       
   171 		$weakCheckbox = $weakRow.find( '.pw-checkbox' );
       
   172 		$weakCheckbox.change( function() {
       
   173 			$submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) );
       
   174 		} );
       
   175 
       
   176 		$pass1 = $('#pass1');
       
   177 		if ( $pass1.length ) {
       
   178 			bindPass1();
       
   179 		}
       
   180 
       
   181 		/**
       
   182 		 * Fix a LastPass mismatch issue, LastPass only changes pass2.
       
   183 		 *
       
   184 		 * This fixes the issue by copying any changes from the hidden
       
   185 		 * pass2 field to the pass1 field, then running check_pass_strength.
       
   186 		 */
       
   187 		$pass2 = $('#pass2').on( inputEvent, function () {
       
   188 			if ( $pass2.val().length > 0 ) {
       
   189 				$pass1.val( $pass2.val() );
       
   190 				$pass2.val('');
       
   191 				currentPass = '';
       
   192 				$pass1.trigger( 'pwupdate' );
       
   193 			}
       
   194 		} );
       
   195 
       
   196 		// Disable hidden inputs to prevent autofill and submission.
       
   197 		if ( $pass1.is( ':hidden' ) ) {
       
   198 			$pass1.prop( 'disabled', true );
       
   199 			$pass2.prop( 'disabled', true );
       
   200 			$pass1Text.prop( 'disabled', true );
       
   201 		}
       
   202 
       
   203 		$passwordWrapper = $pass1Row.find( '.wp-pwd' );
       
   204 		$generateButton  = $pass1Row.find( 'button.wp-generate-pw' );
       
   205 
       
   206 		bindToggleButton();
       
   207 
       
   208 		if ( $generateButton.length ) {
       
   209 			$passwordWrapper.hide();
       
   210 		}
       
   211 
       
   212 		$generateButton.show();
       
   213 		$generateButton.on( 'click', function () {
       
   214 			updateLock = true;
       
   215 
       
   216 			$generateButton.hide();
       
   217 			$passwordWrapper.show();
       
   218 
       
   219 			// Enable the inputs when showing.
       
   220 			$pass1.attr( 'disabled', false );
       
   221 			$pass2.attr( 'disabled', false );
       
   222 			$pass1Text.attr( 'disabled', false );
       
   223 
       
   224 			if ( $pass1Text.val().length === 0 ) {
       
   225 				generatePassword();
       
   226 			}
       
   227 
       
   228 			_.defer( function() {
       
   229 				$pass1Text.focus();
       
   230 				if ( ! _.isUndefined( $pass1Text[0].setSelectionRange ) ) {
       
   231 					$pass1Text[0].setSelectionRange( 0, 100 );
       
   232 				}
       
   233 			}, 0 );
       
   234 		} );
       
   235 
       
   236 		$cancelButton = $pass1Row.find( 'button.wp-cancel-pw' );
       
   237 		$cancelButton.on( 'click', function () {
       
   238 			updateLock = false;
       
   239 
       
   240 			// Clear any entered password.
       
   241 			$pass1Text.val( '' );
       
   242 
       
   243 			// Generate a new password.
       
   244 			wp.ajax.post( 'generate-password' )
       
   245 				.done( function( data ) {
       
   246 					$pass1.data( 'pw', data );
       
   247 				} );
       
   248 
       
   249 			$generateButton.show();
       
   250 			$passwordWrapper.hide();
       
   251 
       
   252 			$weakRow.hide( 0, function () {
       
   253 				$weakCheckbox.removeProp( 'checked' );
       
   254 			} );
       
   255 
       
   256 			// Disable the inputs when hiding to prevent autofill and submission.
       
   257 			$pass1.prop( 'disabled', true );
       
   258 			$pass2.prop( 'disabled', true );
       
   259 			$pass1Text.prop( 'disabled', true );
       
   260 
       
   261 			resetToggle();
       
   262 
       
   263 			if ( $pass1Row.closest( 'form' ).is( '#your-profile' ) ) {
       
   264 				// Clear password field to prevent update
       
   265 				$pass1.val( '' ).trigger( 'pwupdate' );
       
   266 				$submitButtons.prop( 'disabled', false );
       
   267 			}
       
   268 		} );
       
   269 
       
   270 		$pass1Row.closest( 'form' ).on( 'submit', function () {
       
   271 			updateLock = false;
       
   272 
       
   273 			$pass1.prop( 'disabled', false );
       
   274 			$pass2.prop( 'disabled', false );
       
   275 			$pass2.val( $pass1.val() );
       
   276 			$pass1Wrap.removeClass( 'show-password' );
       
   277 		});
       
   278 	}
     3 
   279 
     4 	function check_pass_strength() {
   280 	function check_pass_strength() {
     5 		var pass1 = $('#pass1').val(), pass2 = $('#pass2').val(), strength;
   281 		var pass1 = $('#pass1').val(), strength;
     6 
   282 
     7 		$('#pass-strength-result').removeClass('short bad good strong');
   283 		$('#pass-strength-result').removeClass('short bad good strong');
     8 		if ( ! pass1 ) {
   284 		if ( ! pass1 ) {
     9 			$('#pass-strength-result').html( pwsL10n.empty );
   285 			$('#pass-strength-result').html( '&nbsp;' );
    10 			return;
   286 			return;
    11 		}
   287 		}
    12 
   288 
    13 		strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputBlacklist(), pass2 );
   289 		strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputBlacklist(), pass1 );
    14 
   290 
    15 		switch ( strength ) {
   291 		switch ( strength ) {
       
   292 			case -1:
       
   293 				$( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown );
       
   294 				break;
    16 			case 2:
   295 			case 2:
    17 				$('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
   296 				$('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
    18 				break;
   297 				break;
    19 			case 3:
   298 			case 3:
    20 				$('#pass-strength-result').addClass('good').html( pwsL10n.good );
   299 				$('#pass-strength-result').addClass('good').html( pwsL10n.good );
    28 			default:
   307 			default:
    29 				$('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
   308 				$('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
    30 		}
   309 		}
    31 	}
   310 	}
    32 
   311 
       
   312 	function showOrHideWeakPasswordCheckbox() {
       
   313 		var passStrength = $('#pass-strength-result')[0];
       
   314 
       
   315 		if ( passStrength.className ) {
       
   316 			$pass1.add( $pass1Text ).addClass( passStrength.className );
       
   317 			if ( $( passStrength ).is( '.short, .bad' ) ) {
       
   318 				if ( ! $weakCheckbox.prop( 'checked' ) ) {
       
   319 					$submitButtons.prop( 'disabled', true );
       
   320 				}
       
   321 				$weakRow.show();
       
   322 			} else {
       
   323 				$submitButtons.prop( 'disabled', false );
       
   324 				$weakRow.hide();
       
   325 			}
       
   326 		}
       
   327 	}
       
   328 
    33 	$(document).ready( function() {
   329 	$(document).ready( function() {
    34 		var $colorpicker, $stylesheet, user_id, current_user_id,
   330 		var $colorpicker, $stylesheet, user_id, current_user_id,
    35 			select = $( '#display_name' );
   331 			select       = $( '#display_name' ),
    36 
   332 			current_name = select.val(),
    37 		$('#pass1').val('').on( 'input propertychange', check_pass_strength );
   333 			greeting     = $( '#wp-admin-bar-my-account' ).find( '.display-name' );
    38 		$('#pass2').val('').on( 'input propertychange', check_pass_strength );
   334 
       
   335 		$('#pass1').val('').on( inputEvent + ' pwupdate', check_pass_strength );
    39 		$('#pass-strength-result').show();
   336 		$('#pass-strength-result').show();
    40 		$('.color-palette').click( function() {
   337 		$('.color-palette').click( function() {
    41 			$(this).siblings('input[name="admin_color"]').prop('checked', true);
   338 			$(this).siblings('input[name="admin_color"]').prop('checked', true);
    42 		});
   339 		});
    43 
   340 
    73 							'text': val
   370 							'text': val
    74 						}).appendTo( select );
   371 						}).appendTo( select );
    75 					}
   372 					}
    76 				});
   373 				});
    77 			});
   374 			});
       
   375 
       
   376 			/**
       
   377 			 * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile.
       
   378 			 */
       
   379 			select.on( 'change', function() {
       
   380 				if ( user_id !== current_user_id ) {
       
   381 					return;
       
   382 				}
       
   383 
       
   384 				var display_name = $.trim( this.value ) || current_name;
       
   385 
       
   386 				greeting.text( display_name );
       
   387 			} );
    78 		}
   388 		}
    79 
   389 
    80 		$colorpicker = $( '#color-picker' );
   390 		$colorpicker = $( '#color-picker' );
    81 		$stylesheet = $( '#colors-css' );
   391 		$stylesheet = $( '#colors-css' );
    82 		user_id = $( 'input#user_id' ).val();
   392 		user_id = $( 'input#user_id' ).val();
   124 						$( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
   434 						$( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme );
   125 					}
   435 					}
   126 				});
   436 				});
   127 			}
   437 			}
   128 		});
   438 		});
       
   439 
       
   440 		bindPasswordForm();
   129 	});
   441 	});
   130 
   442 
   131 	$( '#destroy-sessions' ).on( 'click', function( e ) {
   443 	$( '#destroy-sessions' ).on( 'click', function( e ) {
   132 		var $this = $(this);
   444 		var $this = $(this);
   133 
   445 
   144 		});
   456 		});
   145 
   457 
   146 		e.preventDefault();
   458 		e.preventDefault();
   147 	});
   459 	});
   148 
   460 
       
   461 	window.generatePassword = generatePassword;
       
   462 
       
   463 	/* Warn the user if password was generated but not saved */
       
   464 	$( window ).on( 'beforeunload', function () {
       
   465 		if ( true === updateLock ) {
       
   466 			return userProfileL10n.warn;
       
   467 		}
       
   468 	} );
       
   469 
   149 })(jQuery);
   470 })(jQuery);