[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 /** 2 * @output wp-admin/js/user-profile.js 3 */ 4 5 /* global ajaxurl, pwsL10n, userProfileL10n */ 6 (function($) { 7 var updateLock = false, 8 __ = wp.i18n.__, 9 $pass1Row, 10 $pass1, 11 $pass2, 12 $weakRow, 13 $weakCheckbox, 14 $toggleButton, 15 $submitButtons, 16 $submitButton, 17 currentPass, 18 $passwordWrapper; 19 20 function generatePassword() { 21 if ( typeof zxcvbn !== 'function' ) { 22 setTimeout( generatePassword, 50 ); 23 return; 24 } else if ( ! $pass1.val() || $passwordWrapper.hasClass( 'is-open' ) ) { 25 // zxcvbn loaded before user entered password, or generating new password. 26 $pass1.val( $pass1.data( 'pw' ) ); 27 $pass1.trigger( 'pwupdate' ); 28 showOrHideWeakPasswordCheckbox(); 29 } else { 30 // zxcvbn loaded after the user entered password, check strength. 31 check_pass_strength(); 32 showOrHideWeakPasswordCheckbox(); 33 } 34 35 /* 36 * This works around a race condition when zxcvbn loads quickly and 37 * causes `generatePassword()` to run prior to the toggle button being 38 * bound. 39 */ 40 bindToggleButton(); 41 42 // Install screen. 43 if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) { 44 // Show the password not masked if admin_password hasn't been posted yet. 45 $pass1.attr( 'type', 'text' ); 46 } else { 47 // Otherwise, mask the password. 48 $toggleButton.trigger( 'click' ); 49 } 50 51 // Once zxcvbn loads, passwords strength is known. 52 $( '#pw-weak-text-label' ).text( __( 'Confirm use of weak password' ) ); 53 54 // Focus the password field. 55 $( $pass1 ).trigger( 'focus' ); 56 } 57 58 function bindPass1() { 59 currentPass = $pass1.val(); 60 61 if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) { 62 generatePassword(); 63 } 64 65 $pass1.on( 'input' + ' pwupdate', function () { 66 if ( $pass1.val() === currentPass ) { 67 return; 68 } 69 70 currentPass = $pass1.val(); 71 72 // Refresh password strength area. 73 $pass1.removeClass( 'short bad good strong' ); 74 showOrHideWeakPasswordCheckbox(); 75 } ); 76 } 77 78 function resetToggle( show ) { 79 $toggleButton 80 .attr({ 81 'aria-label': show ? __( 'Show password' ) : __( 'Hide password' ) 82 }) 83 .find( '.text' ) 84 .text( show ? __( 'Show' ) : __( 'Hide' ) ) 85 .end() 86 .find( '.dashicons' ) 87 .removeClass( show ? 'dashicons-hidden' : 'dashicons-visibility' ) 88 .addClass( show ? 'dashicons-visibility' : 'dashicons-hidden' ); 89 } 90 91 function bindToggleButton() { 92 if ( !! $toggleButton ) { 93 // Do not rebind. 94 return; 95 } 96 $toggleButton = $pass1Row.find('.wp-hide-pw'); 97 $toggleButton.show().on( 'click', function () { 98 if ( 'password' === $pass1.attr( 'type' ) ) { 99 $pass1.attr( 'type', 'text' ); 100 resetToggle( false ); 101 } else { 102 $pass1.attr( 'type', 'password' ); 103 resetToggle( true ); 104 } 105 }); 106 } 107 108 /** 109 * Handle the password reset button. Sets up an ajax callback to trigger sending 110 * a password reset email. 111 */ 112 function bindPasswordResetLink() { 113 $( '#generate-reset-link' ).on( 'click', function() { 114 var $this = $(this), 115 data = { 116 'user_id': userProfileL10n.user_id, // The user to send a reset to. 117 'nonce': userProfileL10n.nonce // Nonce to validate the action. 118 }; 119 120 // Remove any previous error messages. 121 $this.parent().find( '.notice-error' ).remove(); 122 123 // Send the reset request. 124 var resetAction = wp.ajax.post( 'send-password-reset', data ); 125 126 // Handle reset success. 127 resetAction.done( function( response ) { 128 addInlineNotice( $this, true, response ); 129 } ); 130 131 // Handle reset failure. 132 resetAction.fail( function( response ) { 133 addInlineNotice( $this, false, response ); 134 } ); 135 136 }); 137 138 } 139 140 /** 141 * Helper function to insert an inline notice of success or failure. 142 * 143 * @param {jQuery Object} $this The button element: the message will be inserted 144 * above this button 145 * @param {bool} success Whether the message is a success message. 146 * @param {string} message The message to insert. 147 */ 148 function addInlineNotice( $this, success, message ) { 149 var resultDiv = $( '<div />' ); 150 151 // Set up the notice div. 152 resultDiv.addClass( 'notice inline' ); 153 154 // Add a class indicating success or failure. 155 resultDiv.addClass( 'notice-' + ( success ? 'success' : 'error' ) ); 156 157 // Add the message, wrapping in a p tag, with a fadein to highlight each message. 158 resultDiv.text( $( $.parseHTML( message ) ).text() ).wrapInner( '<p />'); 159 160 // Disable the button when the callback has succeeded. 161 $this.prop( 'disabled', success ); 162 163 // Remove any previous notices. 164 $this.siblings( '.notice' ).remove(); 165 166 // Insert the notice. 167 $this.before( resultDiv ); 168 } 169 170 function bindPasswordForm() { 171 var $generateButton, 172 $cancelButton; 173 174 $pass1Row = $( '.user-pass1-wrap, .user-pass-wrap, .reset-pass-submit' ); 175 176 // Hide the confirm password field when JavaScript support is enabled. 177 $('.user-pass2-wrap').hide(); 178 179 $submitButton = $( '#submit, #wp-submit' ).on( 'click', function () { 180 updateLock = false; 181 }); 182 183 $submitButtons = $submitButton.add( ' #createusersub' ); 184 185 $weakRow = $( '.pw-weak' ); 186 $weakCheckbox = $weakRow.find( '.pw-checkbox' ); 187 $weakCheckbox.on( 'change', function() { 188 $submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) ); 189 } ); 190 191 $pass1 = $('#pass1'); 192 if ( $pass1.length ) { 193 bindPass1(); 194 } else { 195 // Password field for the login form. 196 $pass1 = $( '#user_pass' ); 197 } 198 199 /* 200 * Fix a LastPass mismatch issue, LastPass only changes pass2. 201 * 202 * This fixes the issue by copying any changes from the hidden 203 * pass2 field to the pass1 field, then running check_pass_strength. 204 */ 205 $pass2 = $( '#pass2' ).on( 'input', function () { 206 if ( $pass2.val().length > 0 ) { 207 $pass1.val( $pass2.val() ); 208 $pass2.val(''); 209 currentPass = ''; 210 $pass1.trigger( 'pwupdate' ); 211 } 212 } ); 213 214 // Disable hidden inputs to prevent autofill and submission. 215 if ( $pass1.is( ':hidden' ) ) { 216 $pass1.prop( 'disabled', true ); 217 $pass2.prop( 'disabled', true ); 218 } 219 220 $passwordWrapper = $pass1Row.find( '.wp-pwd' ); 221 $generateButton = $pass1Row.find( 'button.wp-generate-pw' ); 222 223 bindToggleButton(); 224 225 $generateButton.show(); 226 $generateButton.on( 'click', function () { 227 updateLock = true; 228 229 // Make sure the password fields are shown. 230 $generateButton.not( '.skip-aria-expanded' ).attr( 'aria-expanded', 'true' ); 231 $passwordWrapper 232 .show() 233 .addClass( 'is-open' ); 234 235 // Enable the inputs when showing. 236 $pass1.attr( 'disabled', false ); 237 $pass2.attr( 'disabled', false ); 238 239 // Set the password to the generated value. 240 generatePassword(); 241 242 // Show generated password in plaintext by default. 243 resetToggle ( false ); 244 245 // Generate the next password and cache. 246 wp.ajax.post( 'generate-password' ) 247 .done( function( data ) { 248 $pass1.data( 'pw', data ); 249 } ); 250 } ); 251 252 $cancelButton = $pass1Row.find( 'button.wp-cancel-pw' ); 253 $cancelButton.on( 'click', function () { 254 updateLock = false; 255 256 // Disable the inputs when hiding to prevent autofill and submission. 257 $pass1.prop( 'disabled', true ); 258 $pass2.prop( 'disabled', true ); 259 260 // Clear password field and update the UI. 261 $pass1.val( '' ).trigger( 'pwupdate' ); 262 resetToggle( false ); 263 264 // Hide password controls. 265 $passwordWrapper 266 .hide() 267 .removeClass( 'is-open' ); 268 269 // Stop an empty password from being submitted as a change. 270 $submitButtons.prop( 'disabled', false ); 271 272 $generateButton.attr( 'aria-expanded', 'false' ); 273 } ); 274 275 $pass1Row.closest( 'form' ).on( 'submit', function () { 276 updateLock = false; 277 278 $pass1.prop( 'disabled', false ); 279 $pass2.prop( 'disabled', false ); 280 $pass2.val( $pass1.val() ); 281 }); 282 } 283 284 function check_pass_strength() { 285 var pass1 = $('#pass1').val(), strength; 286 287 $('#pass-strength-result').removeClass('short bad good strong empty'); 288 if ( ! pass1 || '' === pass1.trim() ) { 289 $( '#pass-strength-result' ).addClass( 'empty' ).html( ' ' ); 290 return; 291 } 292 293 strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputDisallowedList(), pass1 ); 294 295 switch ( strength ) { 296 case -1: 297 $( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown ); 298 break; 299 case 2: 300 $('#pass-strength-result').addClass('bad').html( pwsL10n.bad ); 301 break; 302 case 3: 303 $('#pass-strength-result').addClass('good').html( pwsL10n.good ); 304 break; 305 case 4: 306 $('#pass-strength-result').addClass('strong').html( pwsL10n.strong ); 307 break; 308 case 5: 309 $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch ); 310 break; 311 default: 312 $('#pass-strength-result').addClass('short').html( pwsL10n['short'] ); 313 } 314 } 315 316 function showOrHideWeakPasswordCheckbox() { 317 var passStrength = $('#pass-strength-result')[0]; 318 319 if ( passStrength.className ) { 320 $pass1.addClass( passStrength.className ); 321 if ( $( passStrength ).is( '.short, .bad' ) ) { 322 if ( ! $weakCheckbox.prop( 'checked' ) ) { 323 $submitButtons.prop( 'disabled', true ); 324 } 325 $weakRow.show(); 326 } else { 327 if ( $( passStrength ).is( '.empty' ) ) { 328 $submitButtons.prop( 'disabled', true ); 329 $weakCheckbox.prop( 'checked', false ); 330 } else { 331 $submitButtons.prop( 'disabled', false ); 332 } 333 $weakRow.hide(); 334 } 335 } 336 } 337 338 $( function() { 339 var $colorpicker, $stylesheet, user_id, current_user_id, 340 select = $( '#display_name' ), 341 current_name = select.val(), 342 greeting = $( '#wp-admin-bar-my-account' ).find( '.display-name' ); 343 344 $( '#pass1' ).val( '' ).on( 'input' + ' pwupdate', check_pass_strength ); 345 $('#pass-strength-result').show(); 346 $('.color-palette').on( 'click', function() { 347 $(this).siblings('input[name="admin_color"]').prop('checked', true); 348 }); 349 350 if ( select.length ) { 351 $('#first_name, #last_name, #nickname').on( 'blur.user_profile', function() { 352 var dub = [], 353 inputs = { 354 display_nickname : $('#nickname').val() || '', 355 display_username : $('#user_login').val() || '', 356 display_firstname : $('#first_name').val() || '', 357 display_lastname : $('#last_name').val() || '' 358 }; 359 360 if ( inputs.display_firstname && inputs.display_lastname ) { 361 inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname; 362 inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname; 363 } 364 365 $.each( $('option', select), function( i, el ){ 366 dub.push( el.value ); 367 }); 368 369 $.each(inputs, function( id, value ) { 370 if ( ! value ) { 371 return; 372 } 373 374 var val = value.replace(/<\/?[a-z][^>]*>/gi, ''); 375 376 if ( inputs[id].length && $.inArray( val, dub ) === -1 ) { 377 dub.push(val); 378 $('<option />', { 379 'text': val 380 }).appendTo( select ); 381 } 382 }); 383 }); 384 385 /** 386 * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile. 387 */ 388 select.on( 'change', function() { 389 if ( user_id !== current_user_id ) { 390 return; 391 } 392 393 var display_name = this.value.trim() || current_name; 394 395 greeting.text( display_name ); 396 } ); 397 } 398 399 $colorpicker = $( '#color-picker' ); 400 $stylesheet = $( '#colors-css' ); 401 user_id = $( 'input#user_id' ).val(); 402 current_user_id = $( 'input[name="checkuser_id"]' ).val(); 403 404 $colorpicker.on( 'click.colorpicker', '.color-option', function() { 405 var colors, 406 $this = $(this); 407 408 if ( $this.hasClass( 'selected' ) ) { 409 return; 410 } 411 412 $this.siblings( '.selected' ).removeClass( 'selected' ); 413 $this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true ); 414 415 // Set color scheme. 416 if ( user_id === current_user_id ) { 417 // Load the colors stylesheet. 418 // The default color scheme won't have one, so we'll need to create an element. 419 if ( 0 === $stylesheet.length ) { 420 $stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' ); 421 } 422 $stylesheet.attr( 'href', $this.children( '.css_url' ).val() ); 423 424 // Repaint icons. 425 if ( typeof wp !== 'undefined' && wp.svgPainter ) { 426 try { 427 colors = JSON.parse( $this.children( '.icon_colors' ).val() ); 428 } catch ( error ) {} 429 430 if ( colors ) { 431 wp.svgPainter.setColors( colors ); 432 wp.svgPainter.paint(); 433 } 434 } 435 436 // Update user option. 437 $.post( ajaxurl, { 438 action: 'save-user-color-scheme', 439 color_scheme: $this.children( 'input[name="admin_color"]' ).val(), 440 nonce: $('#color-nonce').val() 441 }).done( function( response ) { 442 if ( response.success ) { 443 $( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme ); 444 } 445 }); 446 } 447 }); 448 449 bindPasswordForm(); 450 bindPasswordResetLink(); 451 }); 452 453 $( '#destroy-sessions' ).on( 'click', function( e ) { 454 var $this = $(this); 455 456 wp.ajax.post( 'destroy-sessions', { 457 nonce: $( '#_wpnonce' ).val(), 458 user_id: $( '#user_id' ).val() 459 }).done( function( response ) { 460 $this.prop( 'disabled', true ); 461 $this.siblings( '.notice' ).remove(); 462 $this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' ); 463 }).fail( function( response ) { 464 $this.siblings( '.notice' ).remove(); 465 $this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' ); 466 }); 467 468 e.preventDefault(); 469 }); 470 471 window.generatePassword = generatePassword; 472 473 // Warn the user if password was generated but not saved. 474 $( window ).on( 'beforeunload', function () { 475 if ( true === updateLock ) { 476 return __( 'Your new password has not been saved.' ); 477 } 478 } ); 479 480 /* 481 * We need to generate a password as soon as the Reset Password page is loaded, 482 * to avoid double clicking the button to retrieve the first generated password. 483 * See ticket #39638. 484 */ 485 $( function() { 486 if ( $( '.reset-pass-submit' ).length ) { 487 $( '.reset-pass-submit button.wp-generate-pw' ).trigger( 'click' ); 488 } 489 }); 490 491 })(jQuery);
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Nov 23 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |